package com.itlong.cloud.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.itlong.cloud.POJO.DTO.app.AppDeviceOrderDTO;
import com.itlong.cloud.POJO.DTO.app.AppElevatorAuthDTO;
import com.itlong.cloud.POJO.DTO.app.CreateDeviceMarkDTO;
import com.itlong.cloud.POJO.DTO.property.IotCloudElevatorStateDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.app.*;
import com.itlong.cloud.POJO.VO.common.DeviceOnlineVO;
import com.itlong.cloud.POJO.VO.common.ProjectIotInfo;
import com.itlong.cloud.POJO.VO.common.QrcodeUserInfoVO;
import com.itlong.cloud.POJO.VO.property.*;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.app.dao.IAppCloudElevatorCallStatusDao;
import com.itlong.cloud.app.dao.IAppDeviceDao;
import com.itlong.cloud.app.dao.IAppVisitorPassCodeRecordDao;
import com.itlong.cloud.app.service.IAppDeviceService;
import com.itlong.cloud.commons.service.ISendIotCallElevatorService;
import com.itlong.cloud.commons.thread.queue.process.queue.SendIotCallElevatorQueue;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IDeviceCloudIntercomInfoDao;
import com.itlong.cloud.property.dao.IDeviceEntranceInfoDao;
import com.itlong.cloud.property.dao.IPropertyElevatorDao;
import com.itlong.cloud.property.dao.IPropertyEquipDao;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.network.https.HttpsPost;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.security.NoSuchProviderException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * <desc>
 *      App设备信息业务处理接口实现类
 * </desc>
 *
 * @createDate 2017/10/23
 */
@Service
@RefreshScope
public class AppDeviceServiceImpl implements IAppDeviceService{
    private static final Logger LOG = LoggerFactory.getLogger(AppDeviceServiceImpl.class);

    @Autowired
    ISendIotCallElevatorService sendIotCallElevatorService;

    @Autowired
    SendIotCallElevatorQueue sendIotCallElevatorQueue;

    @Autowired
    IAppDeviceDao iAppDeviceDao;

    //物业电梯持久层接口
    @Autowired
    private IPropertyElevatorDao iPropertyElevatorDao;

    //物业门禁持久层接口
    @Autowired
    private IDeviceEntranceInfoDao iDeviceEntranceInfoDao;

    //物业云对讲持久层接口
    @Autowired
    private IDeviceCloudIntercomInfoDao iDeviceCloudIntercomInfoDao;

    @Autowired
    private IPropertyEquipDao iPropertyEquipDao;

    @Autowired
    RedisService redisService;

    @Autowired
    IAppVisitorPassCodeRecordDao iAppVisitorPassCodeRecordDao;

    @Value("${" + PlatformConstants.OFFLINE_PLATFORM_CALL_ELEVATOR_URL + "}")
    private String offlinePLatformDomainByCallElevatorUrl;

    @Autowired
    MessageSender messageSender;

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock writeLock;

    @Autowired
    IAppCloudElevatorCallStatusDao iAppCloudElevatorCallStatusDao;

    //二维码环境标识
    @Value("${" + PlatformConstants.APP_QRCODE_RUN_ENVIRONMENT + "}")
    String qrcodeRunEnvironment;

    ExecutorService cachedThreadPool;

    @PostConstruct
    public void init(){
        writeLock = lock.writeLock();
        cachedThreadPool= Executors.newFixedThreadPool(50);
    }


    /**
     * <desc>
     *      解析某个设备的排序值
     * <desc/>
     *
     * @param orders 排序值数组, 排序值格式：'00010002'，表示 1号设备排序为 2
     * @param deviceUnique 设备唯一码： 8888888820001
     * @return
     * @author Chunjian.G
     * @createDate 2017-11-06
     */
    private String parseDeviceOrder(String[] orders, String deviceUnique){
        if (null == orders || orders.length == 0
                || null == deviceUnique || !deviceUnique.trim().matches("[0-9]{13}")){
            return null;
        }
        String devId = StringHandlerUtil.getDeviceIdByDeviceUnique(deviceUnique);
        if(devId!=null) {
            for (String order : orders) {
                if (order.startsWith(devId)) {
                    String position = StringHandlerUtil.copySubStr(order, 4, 4);
                    return Integer.toString(StringHandlerUtil.strToIntDef(position, 0));
                }
            }
        }
        return null;
    }



    /**
     * <desc>
     *      获取用户设备信息
     * </desc>
     *
     * @param userId 用户id
     * @param projectIds 项目id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/08
     */
    @Override
    public List<AppGetUserDevicesListVO> getUserDevicesList(String userId,String projectIds) throws Exception {
        List<AppGetUserDevicesListVO> list=new ArrayList<>();
        String[] arrayProject=StringHandlerUtil.splitString(projectIds);
        if(arrayProject.length>0){
            for(String projectId:arrayProject) {
                //门禁设备信息
                List<AppDoorDevicesVO> doors = this.getDoorDevices(userId,projectId,0);
                //电梯设备信息
                List<AppFloorDevicesVO> floors=this.getFloorDevices(userId,projectId,0);
//                云对讲设备信息
                List<AppCloudIntercomsVO> clouds=this.getCloudIntercoms(userId,projectId,0);
                AppGetUserDevicesListVO vo=new AppGetUserDevicesListVO();
                List<AppCloudAndEntranceDeviceVO> ces=new ArrayList<>();
                //查询项目下云对讲是否有权限
                String cloudStatus=iAppDeviceDao.getProjectIsSmartCommunity(projectId);
                if(StringUtils.isNotBlank(cloudStatus)){
                    vo.setCloudStatus(cloudStatus);
                }else{
                    vo.setCloudStatus("0");
                }
                vo.setProjectId(projectId);
                //电梯排序
                if(floors!=null && !floors.isEmpty()) {
                    //电梯去null
                    floors.forEach(floor->{
                        floor=(AppFloorDevicesVO)StringHandlerUtil.formatString(floor);
                    });
                }
                vo.setFloorDevices(floors);
                if(doors!=null) {
                    for (AppDoorDevicesVO door : doors) {
                        AppCloudAndEntranceDeviceVO doorVO = new AppCloudAndEntranceDeviceVO();
                        doorVO.setEntranceDeviceVO(door.getDeviceName(), door.getDeviceUnique(), door.getProjectId(),
                                door.getProtocolVersion(), door.getThreshold(), door.getDoorAuth(),
                                door.getCardNum(), door.getValiTime(), door.getPosition());
                        ces.add((AppCloudAndEntranceDeviceVO) StringHandlerUtil.formatString(doorVO));
                    }
                }
                if(clouds!=null) {
                    for (AppCloudIntercomsVO cloud : clouds) {
                        AppCloudAndEntranceDeviceVO cloudVO = new AppCloudAndEntranceDeviceVO();
                        cloudVO.setCloudVO(cloud.getDeviceName(), cloud.getDeviceUnique(), cloud.getProjectId(),
                                cloud.getCardNum(), cloud.getRoomIds(), cloud.getValiTime(), cloud.getSipAccount(),
                                cloud.getRoomNum(), cloud.getPosition(),cloud.getClientAccount());
                        ces.add((AppCloudAndEntranceDeviceVO) StringHandlerUtil.formatString(cloudVO));
                    }
                }
                vo=(AppGetUserDevicesListVO)StringHandlerUtil.formatString(vo);
                vo.setDoorDevices(ces);
                list.add(vo);
            }
            return list;
        }
        return null;
    }

    /**
     * <desc>
     *      获取项目云对讲启用状态
     * </desc>
     *
     * @param projectId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/04/17
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getProjectIsSmartCommunity(String projectId){
        return iAppDeviceDao.getProjectIsSmartCommunity(projectId);
    }

    /**
     * <desc>
     *      设置云电梯专梯模式
     * </desc>
     *
     * @param deviceUnique
     * @author Jiaqi.X
     * @createDate 2019/01/22
     */
    @Override
    public void setCloudElevatorSpecialUseModel(String deviceUnique,String model) throws Exception {
        CloudElevatorVO elevator = iAppDeviceDao.getElevatorNameAndProductKeyByDeviceUnique(deviceUnique);
        List<Map<String,Object>> cmdControls = new ArrayList<>();
        Map<String,Object> message = new HashMap<>();
        Map<String,Object> huaweiIotMessage = new HashMap<>();
        Map<String, Object> control = new HashMap<>();
        control.put("productKey", elevator.getIotProductKey());
        message.put("sourceFrom","itlong");
        message.put("snr",1);
        message.put("cmd","1005");
        message.put("timestamp",(new Date()).getTime()+"");
        huaweiIotMessage.put("sourceFrom","itlong");
        huaweiIotMessage.put("snr",LogicIdUtil.bussinessId());
        huaweiIotMessage.put("cmd","1005");
        huaweiIotMessage.put("timestamp",(new Date()).getTime()+"");
        huaweiIotMessage.put("mode",model);
        Map<String,Object> data = new HashMap<>();
        data.put("mode",model);
        message.put("data",data);
        control.put("message", JsonUtil.toJSON(message));
        control.put("topic", "/" + elevator.getDeviceUnique() + (elevator.getIotVersion() == 1 ? "/user" : "") + IotCloudCtrlInstructEnum.DEVICECMD.getUrl());
        control.put("serviceId","SettingService");
        control.put("commandName","setMode");
        control.put("huaweiIotMessage",JsonUtil.toJSON(huaweiIotMessage));
        cmdControls.add(control);
        this.sendCloudElevatorMessage(new ArrayList<>(),cmdControls);
    }

    /**
     * <desc>
     *      获取呼梯需要的云电梯信息
     * </desc>
     *
     * @param deviceUnique
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/11
     */
    @Override
    public CloudElevatorVO getCallElevatorInfo(String deviceUnique) {
        return iAppDeviceDao.getCallElevatorInfo(deviceUnique);
    }

    /**
     * <desc>
     *      预约呼梯
     * </desc>
     *
     * @param deviceUnique 设备序列号
     * @param sourceFrom 来源 （app传itlong）
     * @param startingFloor 起始楼层（真实楼层）
     * @param gotoFloor 目的楼层（真实楼层）
     * @param floor 呼梯楼层（真实楼层）多个，号分隔
     * @param callType 呼梯类型 对应枚举类 CloudElevatorCallTypeEnum
     * @param seconds 秒
     * @param snr 呼梯流水号
     * @return
     * @author Jiaqi.X
     * @createDate 2018/04/12
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Boolean cloudElevatorCall(String deviceUnique,String sourceFrom,String startingFloor,
                                     String gotoFloor,String floor,Integer callType,Integer seconds,Integer callSource,
                                     String robotId,String snr,Integer ctrElevator, Integer isAPI, String upDown, String userId, String requestId){
        try {
            //snr如果为null
            if (StringUtils.isBlank(snr)) {
                snr = LogicIdUtil.bussinessId();
                LOG.info("【呼梯日志 requestId snr】{} {}", requestId, snr);
            }
            long snrLong = 0L;
            try {
                snrLong = Long.parseLong(snr);
            } catch (Exception e) {
                e.printStackTrace();
            }
            ProjectIotInfo projectIotInfo = iAppDeviceDao.getProjectIotInfoByProjectId(StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique),deviceUnique,StringHandlerUtil.getDeviceTypeByDeviceUnique(deviceUnique));
            if (projectIotInfo == null) {
                LOG.error("【云电梯呼梯失败，查询不到该云电梯设备】deviceUnique={}", deviceUnique);
                return false;
            }
            if(projectIotInfo.getIotFlag() == 1) {
                CloudElevatorVO elevator = iAppDeviceDao.getElevatorNameAndProductKeyByDeviceUnique(deviceUnique);
                //外呼指令
                Map<String, Object> outData = null;
//            检测是否是群控器
                Map<String, Object> controller = iAppDeviceDao.getControllerDeviceUnique(deviceUnique);
                //获取电梯权限标识对比群控器的楼层
                Map<String, Object> floors = iAppDeviceDao.getNaturalByRealFloor(gotoFloor, startingFloor, deviceUnique);
                boolean callController = false;
                if (controller != null) {
                    if (floors != null && !floors.isEmpty()) {
                        String upFloor = StringHandlerUtil.getNullOrStringForObject(controller.get("upFloor"));
                        String downFloor = StringHandlerUtil.getNullOrStringForObject(controller.get("downFloor"));
                        Integer toFloor = Integer.valueOf(floors.get("toFloor").toString());
                        Integer fromFloor = Integer.valueOf(floors.get("fromFloor").toString());
                        int realToFloor = Integer.valueOf(floors.get("realToFloor").toString());
                        int realFromFloor = Integer.valueOf(floors.get("realFromFloor").toString());
                        boolean isUp = false;
                        if (realToFloor > realFromFloor) {
                            isUp = true;
                        }
                        String[] upFloors = StringHandlerUtil.splitString(upFloor);
                        String[] downFloors = StringHandlerUtil.splitString(downFloor);
                        if (isUp) {
                            for (String up : upFloors) {
                                if (fromFloor.equals(Integer.valueOf(up))) {
                                    callController = true;
                                    break;
                                }
                            }
                        } else {
                            for (String down : downFloors) {
                                if (fromFloor.equals(Integer.valueOf(down))) {
                                    callController = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if (callType.equals(CloudElevatorCallTypeEnum.OUT.getType())) {
                    outData = new HashMap<>();
                    if (StringUtils.isBlank(elevator.getVersion()) ||
                            Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                        outData.put("upDown", Integer.valueOf(startingFloor) > Integer.valueOf(gotoFloor) ?
                                "1" : "2");
                        outData.put("startingFloor", startingFloor);
                        outData.put("gotoFloor", gotoFloor);
                    } else {
                        outData.put("upDown", Integer.valueOf(startingFloor) > Integer.valueOf(gotoFloor) ?
                                "1" : "2");
                        outData.put("startingFloor", iAppDeviceDao.getLogicFloorByFloorNum(startingFloor, deviceUnique));
                         outData.put("gotoFloor", iAppDeviceDao.getLogicFloorByFloorNum(gotoFloor, deviceUnique));
                    }
                    // 是否API请求 1：API请求
                    Integer requestAPI = 1;
                    if (isAPI != null && requestAPI.equals(isAPI)){
                        outData.put("time", "");
                        if (StringUtils.isNotBlank(floor)){
                            outData.put("floor", floor);
                        }
                        if (StringUtils.isNotBlank(upDown)){
                            outData.put("upDown", upDown);
                        }
                    }

                    // TODO: 2020/7/17 Wenchao.L：此处if else判断可以优化成switch判断，并且类型判断与put要一致
                    if (callSource == CallElevatorSourceTypeEnum.APP.getType() || callSource == CallElevatorSourceTypeEnum.MINIPROGRAM.getType()) {
                        outData.put("type", CallElevatorSourceTypeEnum.APP.getType() + "");
                        if(callSource == CallElevatorSourceTypeEnum.APP.getType()){
                            //判断是否符合外呼控制器场景
                            Integer checkOut = iAppDeviceDao.checkElevatorBindOutController(deviceUnique);
                            if(callController && checkOut > 0){
                                outData.put("startingFloorCallMode","1");
                            }
                        }
                    } else {
                        outData.put("type", CallElevatorSourceTypeEnum.ROBOT.getType() + "");
                    }
                    if (StringUtils.isNotBlank(robotId)) {
                        outData.put("robotId", robotId);
                    }
                    if (StringUtils.isNotBlank(snr)) {
                        outData.put("snr", snrLong);
                    }
                }
                //内呼指令
                Map<String, Object> inData = null;
                if (callType.equals(CloudElevatorCallTypeEnum.IN.getType())) {
                    inData = new HashMap<>();
                    inData.put("module", "0");

                    if (StringUtils.isNotBlank(elevator.getVersion()) &&
                            Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                        inData.put("mode", "1");
                    }
                    String[] floorArr = StringHandlerUtil.splitString(floor);
                    if (floorArr.length > 1) {
                        inData.put("time", "10");//楼层开放时长 30秒
                    } else {
                        inData.put("time", "0");//自动登记楼层
                    }
                    if (StringUtils.isBlank(elevator.getVersion()) ||
                            Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                        List<String> plusFloor = new ArrayList<>();         //正楼层
                        List<String> negativeFloor = new ArrayList<>();     //负楼层
                        for (String f : floorArr) {
                            if (Integer.valueOf(f) > 0) {
                                plusFloor.add(f);
                            } else {
                                negativeFloor.add(Math.abs(Integer.valueOf(f)) + "");
                            }
                        }
                        //将正负楼层转为十六进制字符串
                        if (plusFloor.size() > 0) {
                            inData.put("floor", StringHandlerUtil.getCloudElevatorInFloor(
                                    StringUtils.join(plusFloor.toArray(new String[plusFloor.size()]), ","), 1));
                        }
                        if (negativeFloor.size() > 0) {
                            inData.put("negativeFloor", StringHandlerUtil.getCloudElevatorInFloor(
                                    StringUtils.join(negativeFloor.toArray(new String[negativeFloor.size()]), ","), 1).substring(0, 2));
                        }
                    } else {
                        inData.put("floor", iAppDeviceDao.getLogicalFloorsByFloorNum(Arrays.asList(floorArr), deviceUnique));
                    }
                    if (callSource == CallElevatorSourceTypeEnum.ROBOT.getType()) {
                        inData.put("type", CallElevatorSourceTypeEnum.ROBOT.getType() + "");
                    } else {
                        inData.put("type", CallElevatorSourceTypeEnum.APP.getType() + "");
                    }
                    if (StringUtils.isNotBlank(snr)) {
                        inData.put("snr", snrLong);
                    }
                }
                List<Map<String, Object>> cmdControls = new ArrayList<>();
                //开关门指令
                if (callType == CloudElevatorCallTypeEnum.OPEN.getType() || callType == CloudElevatorCallTypeEnum.CLOSE.getType()) {
                    Map<String, Object> message = new HashMap<>();
                    Map<String, Object> control = new HashMap<>();
                    control.put("productKey", elevator.getIotProductKey());
                    message.put("sourceFrom", "itlong");
                    message.put("snr", snrLong);
                    message.put("timestamp", (new Date()).getTime() + "");
                    message.put("cmd", "1003");
                    Map<String, Object> data = new HashMap<>();
                    data.put(callType == CloudElevatorCallTypeEnum.OPEN.getType() ? "fOpenCtrl" : "fCloseCtrl", seconds.toString());
                    message.put("data", data);
                    control.put("message", JsonUtil.toJSON(message));
                    control.put("topic", "/" + deviceUnique + (elevator.getIotVersion() == 1 ? "/user" : "") + IotCloudCtrlInstructEnum.DEVICECMD.getUrl());
                    cmdControls.add(control);
                    this.sendCloudElevatorMessage(new ArrayList<>(), cmdControls);
                }
                if (callType != CloudElevatorCallTypeEnum.OPEN.getType() && callType != CloudElevatorCallTypeEnum.CLOSE.getType() &&
                        elevator != null && StringUtils.isNotBlank(elevator.getIotDeviceId())) {
                    SendCallElevatorMessageTaskPO send = new SendCallElevatorMessageTaskPO(
                            elevator.getVersion(),
                            (ctrElevator == null || ctrElevator == 0) && callController && callType.equals(CloudElevatorCallTypeEnum.OUT.getType()) ? iAppDeviceDao.getControllerProductKey() : elevator.getIotProductKey(),
                            (ctrElevator == null || ctrElevator == 0) && callController && callType.equals(CloudElevatorCallTypeEnum.OUT.getType()) ? controller.get("controller").toString() : deviceUnique, "0", sourceFrom, outData, inData,
                            callType == CloudElevatorCallTypeEnum.OUT.getType() ? 2000 : 0, callType);
                    /*
                        将呼梯消息放入自定义队列
                        此处逻辑删除
                        sendIotCallElevatorQueue.getSendIotCallElevatorQueue().put(send);
                    */
                    send.setSnr(snrLong);
                    sendIotCallElevatorService.send(send);
                    return true;
                }
            }else{
                //华为云iot呼梯
                Map<String,Object> data = new HashMap<>();
                Map<String,Object> message = new HashMap<>();
                data.put("serviceId","SettingService");
                message.put("sourceFrom", "itlong");
                message.put("snr", snr);//文档定义的是String
                message.put("timestamp", (new Date()).getTime() + "");
                if (callType == CloudElevatorCallTypeEnum.OPEN.getType() || callType == CloudElevatorCallTypeEnum.CLOSE.getType()) {
                    //开门
                    data.put("commandName","doorCtrl");
                    data.put("deviceId",projectIotInfo.getHuaweiIotId());
                    message.put("cmd", "1033");
                    message.put(callType == CloudElevatorCallTypeEnum.OPEN.getType() ? "fOpenCtrl" : "fCloseCtrl", seconds.toString());
                }else {
                    //呼梯
                    //检测是否是群控器
                    Map<String, Object> controller = iAppDeviceDao.getControllerDeviceUnique(deviceUnique);
                    //获取电梯权限标识对比群控器的楼层
                    Map<String, Object> floors = iAppDeviceDao.getNaturalByRealFloor(gotoFloor, startingFloor, deviceUnique);
                    boolean callController = false;
                    if (controller != null) {
                        if (!floors.isEmpty()) {
                            String upFloor = StringHandlerUtil.getNullOrStringForObject(controller.get("upFloor"));
                            String downFloor = StringHandlerUtil.getNullOrStringForObject(controller.get("downFloor"));
                            Integer toFloor = Integer.valueOf(floors.get("toFloor").toString());
                            Integer fromFloor = Integer.valueOf(floors.get("fromFloor").toString());
                            int realToFloor = Integer.valueOf(floors.get("realToFloor").toString());
                            int realFromFloor = Integer.valueOf(floors.get("realFromFloor").toString());
                            boolean isUp = false;
                            if (realToFloor > realFromFloor) {
                                isUp = true;
                            }
                            String[] upFloors = StringHandlerUtil.splitString(upFloor);
                            String[] downFloors = StringHandlerUtil.splitString(downFloor);
                            if (isUp) {
                                for (String up : upFloors) {
                                    if (fromFloor.equals(Integer.valueOf(up))) {
                                        callController = true;
                                        break;
                                    }
                                }
                            } else {
                                for (String down : downFloors) {
                                    if (fromFloor.equals(Integer.valueOf(down))) {
                                        callController = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    data.put("commandName","setTravel");
                    message.put("cmd", "1023");
                    message.put("cmdVer", "0");
                    message.put("startingFloor", iAppDeviceDao.getLogicFloorByFloorNum(startingFloor, deviceUnique));
                    message.put("gotoFloor", iAppDeviceDao.getLogicFloorByFloorNum(gotoFloor, deviceUnique));
                    if (Integer.valueOf(startingFloor) > Integer.valueOf(gotoFloor)) {
                        message.put("upDown", "1");
                    } else {
                        message.put("upDown", "2");
                    }
                    if(callController && controller.get("huaweiIotId") !=null && (ctrElevator == null || ctrElevator == 0)){
                        data.put("deviceId",controller.get("huaweiIotId").toString());
                    }else{
                        data.put("deviceId",projectIotInfo.getHuaweiIotId());
                    }
                    Map<String,Object> customData = new HashMap<>();
                    // 是VIP为 true
                    boolean appUserIsVipFlag = appUserIsVip(userId, StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique));
                    // 用户标签，1-VIP
                    Integer appUserVip = 1;
                    if(appUserIsVipFlag) {
                        customData.put("isVip", appUserVip);
                    }

                    if(StringUtils.isNotBlank(robotId) && callSource == CallElevatorSourceTypeEnum.ROBOT.getType()){
                        customData.put("senderType","1");
                        customData.put("robotId",robotId);
                        if(customData.size() > 0) {
                            message.put("customData",JsonUtil.toJSON(customData));
                        }

                    }else{
                        // 是否API请求 1：API请求
                        Integer requestAPI = 1;
                        if (isAPI != null && requestAPI.equals(isAPI)){
                            customData.put("time", "");
                            if (StringUtils.isNotBlank(floor)){
                                customData.put("floor", floor);
                            }
                            // 当SDK 请求时 如第三方 上下行状态不为空 以第三方给出数据为准
                            if (StringUtils.isNotBlank(upDown)){
                                data.put("upDown", upDown);
                                message.put("upDown", upDown);
                            }
                        }
                        Integer checkOut = iAppDeviceDao.checkElevatorBindOutController(deviceUnique);
                        if(callController && checkOut > 0){
                            customData.put("startingFloorCallMode","1");
                        }

                        if(customData.size() > 0) {
                            message.put("customData",JsonUtil.toJSON(customData));
                        }
                    }
                }
                data.put("message",JsonUtil.toJSON(message));
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("data",data);
                //放入requestId
                jsonObject.put("requestId", requestId);
                //LOG.info("【发送呼梯数据】:"+JsonUtil.toJSON(data));
                messageSender.send(RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_QUEUE, jsonObject.toJSONString(),
                        RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_KEY);
                return true;
            }
            LOG.info("【云电梯呼梯失败，查询不到该云电梯设备】deviceUnique:"+deviceUnique);
        }catch (Exception e){
            LOG.error("【云电梯呼梯失败，解析楼层异常】",e);
            return false;
        }
        return false;
    }


    /**
     * <desc>
     *      开放或自动登记楼层
     * </desc>
     *
     * @param deviceUnique 设备序列号
     * @param sourceFrom 来源 （app传itlong）
     * @param floor 呼梯楼层（真实楼层）多个，号分隔
     * @param callType 呼梯类型 对应枚举类 CloudElevatorCallTypeEnum
     * @param seconds 秒
     * @return
     * @author Jiaqi.X
     * @createDate 2018/04/12
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Boolean openOrAutoRegister(String deviceUnique,String sourceFrom,String floor,Integer callType,Integer seconds,Integer callSource, String isRobot, String userId){
        try {
            ProjectIotInfo projectIotInfo = iAppDeviceDao.getProjectIotInfoByProjectId(StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique),
                    deviceUnique,StringHandlerUtil.getDeviceTypeByDeviceUnique(deviceUnique));
            if(projectIotInfo.getIotFlag() == 1) {
                CloudElevatorVO elevator = iAppDeviceDao.getElevatorNameAndProductKeyByDeviceUnique(deviceUnique);
                //外呼指令
                Map<String, Object> outData = null;
                //内呼指令
                Map<String, Object> inData = null;
                if (callType.equals(CloudElevatorCallTypeEnum.IN.getType())) {
                    inData = new HashMap<>();
                    inData.put("module", "0");
                    if (StringUtils.isNotBlank(elevator.getVersion()) &&
                            Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                        inData.put("mode", "1");
                    }
                    String[] floorArr = StringHandlerUtil.splitString(floor);
                    inData.put("time", seconds.toString());//楼层开放时长 30秒
                    if (StringUtils.isBlank(elevator.getVersion()) ||
                            Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                        List<String> plusFloor = new ArrayList<>();         //正楼层
                        List<String> negativeFloor = new ArrayList<>();     //负楼层
                        for (String f : floorArr) {
                            if (Integer.valueOf(f) > 0) {
                                plusFloor.add(f);
                            } else {
                                negativeFloor.add(Math.abs(Integer.valueOf(f)) + "");
                            }
                        }
                        //将正负楼层转为十六进制字符串
                        if (plusFloor.size() > 0) {
                            inData.put("floor", StringHandlerUtil.getCloudElevatorInFloor(
                                    StringUtils.join(plusFloor.toArray(new String[plusFloor.size()]), ","), 1));
                        }
                        if (negativeFloor.size() > 0) {
                            inData.put("negativeFloor", StringHandlerUtil.getCloudElevatorInFloor(
                                    StringUtils.join(negativeFloor.toArray(new String[negativeFloor.size()]), ","), 1).substring(0, 2));
                        }
                    } else {
                        inData.put("floor", iAppDeviceDao.getLogicalFloorsByFloorNum(Arrays.asList(floorArr), deviceUnique));
                    }
                }
                SendCallElevatorMessageTaskPO send = new SendCallElevatorMessageTaskPO(
                        elevator.getVersion(),
                        elevator.getIotProductKey(),
                        deviceUnique, "0", sourceFrom, outData, inData,
                        0, callType);
                //将呼梯消息放入自定义队列
                sendIotCallElevatorQueue.getSendIotCallElevatorQueue().put(send);
            }else{
                //华为云iot开放楼层
                Map<String,Object> data = new HashMap<>();
                Map<String,Object> message = new HashMap<>();
                data.put("serviceId","SettingService");
                data.put("commandName","openFloor");
                data.put("deviceId",projectIotInfo.getHuaweiIotId());
                message.put("sourceFrom","itlong");
                message.put("snr",LogicIdUtil.bussinessId());
                message.put("cmd","1013");
                message.put("timestamp",(new Date()).getTime()+"");
                message.put("cmdVer","0");
                message.put("module","0");
                String[] floors = StringHandlerUtil.splitString(floor);
                List<String> floorsList = Arrays.asList(floors);
                message.put("floor", iAppDeviceDao.getLogicalFloorsByFloorNum(floorsList,deviceUnique));
                message.put("mode","1");
                message.put("time",seconds.toString());
                //自定义数据
                Map<Object, Object> customData = new HashMap<>();
                if(StringUtils.isNotBlank(isRobot) && "1".equals(isRobot)) {
                    customData.put("senderType", "1");
                }
                // 是VIP为 true
                boolean appUserIsVipFlag = appUserIsVip(userId, StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique));
                // 用户标签，1-VIP
                Integer appUserVip = 1;
                if(appUserIsVipFlag) {
                    customData.put("isVip", appUserVip);
                }
                if(customData.size() > 0){
                    message.put("customData",JSON.toJSONString(customData));
                }

                data.put("message",JsonUtil.toJSON(message));
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("data",data);
                messageSender.send(RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_QUEUE, jsonObject.toJSONString(),
                        RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_KEY);
            }
            return true;
        }catch (Exception e){
            LOG.error("【云电梯呼梯失败，解析楼层异常openOrAutoRegister】",e);
            return false;
        }
    }

    /**
     * <desc>
     *      获取电梯实时状态
     * </desc>
     *
     * @param deviceUnique 设备序列号 多个,号分隔
     * @param userId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/04/10
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppCloudElevatorRunState> getCloudElevatorState(String deviceUnique,String userId) throws Exception {
        try {
            //从redis中读取电梯的实时状态
            String[] deviceNames = StringHandlerUtil.splitString(deviceUnique);
            List<AppCloudElevatorRunState> states = new ArrayList<>();
            //需要发送的控制指令集合
            List<Map<String, Object>> controls = new ArrayList<>();
            List<Map<String,Object>> cmdControls = new ArrayList<>();
            Date now = new Date();
            for (String deviceName : deviceNames) {
                CloudElevatorVO elevator;
                try {
                    elevator = iAppDeviceDao.getElevatorNameAndProductKeyByDeviceUnique(deviceName);
                } catch (Exception e) {
                    elevator = null;
                }
                //检测是否是群控器
                Map<String,Object> controller = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUnique(deviceName);
                String upFloor = StringHandlerUtil.getNullOrStringForObject(controller!=null ? controller.get("upFloor") : null);
                String downFloor = StringHandlerUtil.getNullOrStringForObject(controller!=null ? controller.get("downFloor") : null);
                if(controller != null && controller.get("groupConId") != null){
                    String sendStatusCache = redisService.get(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE +
                            controller.get("groupConId").toString() + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                    DeviceOnlineVO controllerOnline = (DeviceOnlineVO) redisService.getObject(RedisConstant.REDIS_IOT_CLOUD_DEVICE_ONLINE_STATE_CACHE + controller.get("groupConId").toString(), DeviceOnlineVO.class);
                    String controllerIotKey = controller.get("iotProductKey") != null ? controller.get("iotProductKey").toString() : null;
                    if (controllerOnline == null || (controller.get("iotDeviceId") != null && StringUtils.isNotBlank(controllerIotKey) && (
                            StringUtils.isBlank(controllerOnline.getStatus())) || controllerOnline.getStatus().equals("OFFLINE"))) {
                        if(StringUtils.isBlank(sendStatusCache)) {
                            sendSelectIotDeviceStatusMessage(controller.get("groupConId").toString(), controller.get("iotProductKey").toString());
                            redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + controller.get("groupConId") + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                    RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME, "false");
                        }
                        continue;
                    } else if ((controllerOnline.getStatus().equals("ONLINE") && now.getTime() > controllerOnline.getTime().getTime())) {
                        sendSelectIotDeviceStatusMessage(controller.get("groupConId").toString(), controller.get("iotProductKey").toString());
                        redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + controller.get("groupConId") + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME, "false");
                    }
                }
                if (elevator != null) {
                    IotCloudElevatorStateDTO dto = JsonUtil.toObject(redisService.getKeysForDevice(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CACHE +
                            deviceName),IotCloudElevatorStateDTO.class);
                    //判断电梯是否在线
                    DeviceOnlineVO online = (DeviceOnlineVO)redisService.getObject(RedisConstant.REDIS_IOT_CLOUD_DEVICE_ONLINE_STATE_CACHE + deviceName, DeviceOnlineVO.class);
                    if(StringUtils.isNotBlank(elevator.getIotDeviceId()) && (online == null || (online!=null && now.getTime() > online.getTime().getTime()))){
                        sendSelectIotDeviceStatusMessage(deviceName, elevator.getIotProductKey());
                    }
                    if (online !=null  && online.getStatus().equals("ONLINE")  &&
                            StringUtils.isNotBlank(elevator.getIotDeviceId())&&(dto == null || (StringUtils.isNotBlank(dto.getTimeout())))) {
                        String sendStatusCache = redisService.get(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE +
                                deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                        if(StringUtils.isBlank(sendStatusCache)) {
                            //发送电梯状态上报控制指令
                            ProjectIotInfo projectIotInfo = iAppDeviceDao.getProjectIotInfoByProjectId(StringHandlerUtil.getProjectIdByDeviceUnique(deviceName),deviceName,StringHandlerUtil.getDeviceTypeByDeviceUnique(deviceName));
                            if(projectIotInfo.getIotFlag() == 1) {
                                Map<String, Object> control = new HashMap<>();
                                control.put("productKey", elevator.getIotProductKey());
                                if (StringUtils.isBlank(elevator.getVersion()) ||
                                        Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                                    JSONObject jsonObject = new JSONObject();
                                    jsonObject.put("timeout", "300");
                                    control.put("message", jsonObject.toJSONString());
                                    control.put("topic", "/" + deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                                    controls.add(control);
                                } else {
                                    JSONObject cmd = new JSONObject();
                                    cmd.put("sourceFrom", "itlong");
                                    cmd.put("snr", LogicIdUtil.bussinessIdLong());
                                    cmd.put("cmd", CloudElevatorIotOrderTypeEnum.REPORTCONTROLLER.getType());
                                    cmd.put("timestamp", (new Date()).getTime() + "");
                                    JSONObject cmdChildChild = new JSONObject();
                                    cmdChildChild.put("timeout", "300");
                                    cmd.put("data", cmdChildChild);
                                    control.put("message", cmd.toJSONString());
                                    control.put("topic", "/" + deviceName + (elevator.getIotVersion() == 1 ? "/user" : "") + IotCloudCtrlInstructEnum.DEVICECMD.getUrl());
                                    cmdControls.add(control);
                                }
                            }else{
                                //发送上报指令
                                Map<String,Object> data = new HashMap<>();
                                Map<String,Object> message = new HashMap<>();
                                data.put("serviceId","SettingService");
                                data.put("commandName","deviceReportCtrl");
                                data.put("deviceId",projectIotInfo.getHuaweiIotId());
                                message.put("sourceFrom","itlong");
                                message.put("snr",LogicIdUtil.bussinessId());
                                message.put("cmd","1001");
                                message.put("timestamp",DateUtil.addCurrentTime(new Date(),3*60*60*1000).getTime()+"");
                                Date date1 = new Date();
                                Date date2 = Calendar.getInstance().getTime();
                                LOG.info(String.format("【date时间函数】：%s 【时间戳】 %s 【Calendar时间函数】%s 【时间戳】%s",date1,date2,date1.getTime(),date2.getTime()));
                                LOG.info("时区信息:{}", DateUtil.getDetailDateTime());
                                message.put("timeout","300");
                                data.put("message",JsonUtil.toJSON(message));
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("data",data);
                                messageSender.send(RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_QUEUE, jsonObject.toJSONString(),
                                        RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_KEY);
                            }
                            redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                    RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME, "false");
                        }
                    }
                    if(StringUtils.isNotBlank(elevator.getIotDeviceId()) && dto!= null){
//                        LOG.info(String.format("【APP获取云电梯状态】:%s",JsonUtil.toJSON(dto)));
                        //返回获取的云电梯状态
                        AppCloudElevatorRunState runState = new AppCloudElevatorRunState();
                        runState.setTimestamp(dto.getTimestamp());
                        runState.setDeviceUnique(deviceName);
                        runState.setCodeName(elevator.getDeviceName());
                        runState.setFloorNum(StringUtils.isBlank(elevator.getVersion()) ||
                                Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040
                                ? iAppDeviceDao.getLogicFloorByFloorNum(dto.getFloor(), deviceName) : StringUtils.isNotBlank(dto.getFloor()) && !dto.getFloor().equals("-") ? dto.getFloor() : "-");
                        if(StringUtils.isNotBlank(runState.getFloorNum())) {
                            runState.setIsFull("0");
                            //app状态为 1:上行  2:下行  3:停层  设备上报状态为：1:下行  2:上行 0：停层
                            if (dto.getUpDown().equals("1")) {
                                runState.setLiftState("2");
                            } else if (dto.getUpDown().equals("2")) {
                                runState.setLiftState("1");
                            } else {
                                runState.setLiftState("3");
                            }
                            runState.setDoorStatus(Integer.valueOf(dto.getFrontDoor()));
                            //查询当前用户预约电梯状态
                            String operateStatus = null;
                            //如果电梯状态为开门状态,查询当前电梯是否为预约完成状态
                            Integer callId = iAppCloudElevatorCallStatusDao.checkSuccessState(userId, deviceName);
                            if (callId != null && callId > 0) {
                                //设置该条信息为已读
                                iAppCloudElevatorCallStatusDao.updateAppRead(callId);
                                operateStatus = CallElevatorOperateStateEnum.SUCCESS.getType().toString();
                            }
                            try {
                                if (StringUtils.isBlank(operateStatus)) {
                                    Map<String, Object> callInfo = iAppCloudElevatorCallStatusDao.getCallInfo(userId, deviceName);
                                    //查询当前是否有预约该电梯设备
                                    if (callInfo != null) {
                                        operateStatus = CallElevatorOperateStateEnum.CALLING.getType().toString();
                                        Integer fromFloor = Integer.valueOf(callInfo.get("fromFloor").toString());
                                        int realToFloor = Integer.valueOf(callInfo.get("realToFloor").toString());
                                        int realFromFloor = Integer.valueOf(callInfo.get("realFromFloor").toString());
                                        boolean isUp = false;
                                        boolean callController = false;
                                        if (realToFloor > realFromFloor) {
                                            isUp = true;
                                        }
                                        if (isUp) {
                                            if (StringUtils.isNotBlank(upFloor)) {
                                                String[] upFloors = StringHandlerUtil.splitString(upFloor);
                                                for (String up : upFloors) {
                                                    if (fromFloor.equals(Integer.valueOf(up))) {
                                                        callController = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        } else {
                                            if (StringUtils.isNotBlank(downFloor)) {
                                                String[] downFloors = StringHandlerUtil.splitString(downFloor);
                                                for (String down : downFloors) {
                                                    if (fromFloor.equals(Integer.valueOf(down))) {
                                                        callController = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        if (callController) {
                                            runState.setDisplayOther(0);
                                        } else {
                                            runState.setDisplayOther(1);
                                        }
                                    } else {
                                        operateStatus = CallElevatorOperateStateEnum.CALL_NULL.getType().toString();
                                    }
                                }
                                runState.setLiftOrderState(operateStatus);
                            }catch (Exception e){
                                //此try catch 暂时处理机器人呼梯存入呼梯记录的楼层为楼层名称导致的报错问题
                            }
                            if(online!=null && online.getStatus().equals("ONLINE")) {
                                runState.setIsOnline("0");
                            }else{
                                LOG.info("=====缓存中存的电梯信息======>{}",online);
                                runState.setIsOnline("1");
                            }
                            states.add(runState);
                        }
                    }
                }
            }
            //发送云电梯控制指令
            sendCloudElevatorMessage(controls, cmdControls);
            return states;
        }catch (Exception e){
            LOG.error("【云电梯获取实时状态异常】",e);
            throw e;
        }
    }


    /**
     * <desc>
     *      获取电梯实时状态(小程序)
     * </desc>
     *
     * @param deviceUnique 设备序列号 多个,号分隔
     * @param userId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/11/29
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MiniCloudElevatorRunStateVO> getCloudElevatorStateForMini(String deviceUnique,String userId, String requestId) throws Exception {
        try {
            //从redis中读取电梯的实时状态
            String[] deviceNames = StringHandlerUtil.splitString(deviceUnique);
            List<MiniCloudElevatorRunStateVO> states = new ArrayList<>();
            //需要发送的控制指令集合
            List<Map<String, Object>> controls = new ArrayList<>();
            List<Map<String,Object>> cmdControls = new ArrayList<>();
            Date now = new Date();
            for (String deviceName : deviceNames) {
                CloudElevatorVO elevator;
                try {
                    elevator = iAppDeviceDao.getElevatorNameAndProductKeyByDeviceUnique(deviceName);
                } catch (Exception e) {
                    elevator = null;
                }
                //检测是否是群控器
                Map<String,Object> controller = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUnique(deviceName);
                String upFloor = StringHandlerUtil.getNullOrStringForObject(controller!=null ? controller.get("upFloor") : null);
                String downFloor = StringHandlerUtil.getNullOrStringForObject(controller!=null ? controller.get("downFloor") : null);
                if(controller != null && controller.get("groupConId") != null){
                    String sendStatusCache = redisService.get(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE +
                            controller.get("groupConId").toString() + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                    DeviceOnlineVO controllerOnline = (DeviceOnlineVO) redisService.getObject(RedisConstant.REDIS_IOT_CLOUD_DEVICE_ONLINE_STATE_CACHE + controller.get("groupConId").toString(), DeviceOnlineVO.class);
                    String controllerIotKey = controller.get("iotProductKey") != null ? controller.get("iotProductKey").toString() : null;
                    if (controllerOnline == null || (controller.get("iotDeviceId") != null && StringUtils.isNotBlank(controllerIotKey) && (
                            StringUtils.isBlank(controllerOnline.getStatus())) || controllerOnline.getStatus().equals("OFFLINE"))) {
                        if(StringUtils.isBlank(sendStatusCache)) {
                            sendSelectIotDeviceStatusMessage(controller.get("groupConId").toString(), controller.get("iotProductKey").toString());
                            redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + controller.get("groupConId") + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                    RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME, "false");
                        }
                        continue;
                    } else if ((controllerOnline.getStatus().equals("ONLINE") && now.getTime() > controllerOnline.getTime().getTime())) {
                        sendSelectIotDeviceStatusMessage(controller.get("groupConId").toString(), controller.get("iotProductKey").toString());
                        redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + controller.get("groupConId") + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME, "false");
                    }
                }
                if (elevator != null) {
                    IotCloudElevatorStateDTO dto = JsonUtil.toObject(redisService.getKeysForDevice(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CACHE +
                            deviceName),IotCloudElevatorStateDTO.class);
                    //判断电梯是否在线
                    DeviceOnlineVO online = (DeviceOnlineVO)redisService.getObject(RedisConstant.REDIS_IOT_CLOUD_DEVICE_ONLINE_STATE_CACHE + deviceName, DeviceOnlineVO.class);
                    if(StringUtils.isNotBlank(elevator.getIotDeviceId()) && (online == null || (online!=null && now.getTime() > online.getTime().getTime()))){
                        sendSelectIotDeviceStatusMessage(deviceName, elevator.getIotProductKey());
                    }

                    if (online !=null  && online.getStatus().equals("ONLINE")  &&
                            StringUtils.isNotBlank(elevator.getIotDeviceId())&&(dto == null || (StringUtils.isNotBlank(dto.getTimeout())))) {
                        String sendStatusCache = redisService.get(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE +
                                deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                        if(StringUtils.isBlank(sendStatusCache)) {
                            //发送电梯状态上报控制指令
                            ProjectIotInfo projectIotInfo = iAppDeviceDao.getProjectIotInfoByProjectId(StringHandlerUtil.getProjectIdByDeviceUnique(deviceName),deviceName,
                                    StringHandlerUtil.getDeviceTypeByDeviceUnique(deviceName));
                            if(projectIotInfo.getIotFlag() == 1) {
                                Map<String, Object> control = new HashMap<>();
                                control.put("productKey", elevator.getIotProductKey());
                                if (StringUtils.isBlank(elevator.getVersion()) ||
                                        Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040) {
                                    JSONObject jsonObject = new JSONObject();
                                    jsonObject.put("timeout", "300");
                                    control.put("message", jsonObject.toJSONString());
                                    control.put("topic", "/" + deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                                    controls.add(control);
                                } else {
                                    JSONObject cmd = new JSONObject();
                                    cmd.put("sourceFrom", "itlong");
                                    cmd.put("snr", 0);
                                    cmd.put("cmd", CloudElevatorIotOrderTypeEnum.REPORTCONTROLLER.getType());
                                    cmd.put("timestamp", (new Date()).getTime() + "");
                                    JSONObject cmdChildChild = new JSONObject();
                                    cmdChildChild.put("timeout", "300");
                                    cmd.put("data", cmdChildChild);
                                    control.put("message", cmd.toJSONString());
                                    control.put("topic", "/" + deviceName + (elevator.getIotVersion() == 1 ? "/user" : "") + IotCloudCtrlInstructEnum.DEVICECMD.getUrl());
                                    cmdControls.add(control);
                                }
                            }else{
                                //发送上报指令
                                Map<String,Object> data = new HashMap<>();
                                Map<String,Object> message = new HashMap<>();
                                data.put("serviceId","SettingService");
                                data.put("commandName","deviceReportCtrl");
                                data.put("deviceId",projectIotInfo.getHuaweiIotId());
                                message.put("sourceFrom","itlong");
                                message.put("snr",LogicIdUtil.bussinessId());
                                message.put("cmd","1001");
                                message.put("timestamp",(new Date()).getTime()+"");
                                message.put("timeout","300");
                                data.put("message",JsonUtil.toJSON(message));
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("data",data);
                                //增加requestId
                                jsonObject.put("requestId", requestId);
                                messageSender.send(RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_QUEUE, jsonObject.toJSONString(),
                                        RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_HUAW_CALL_IOT_PUB_KEY);
                            }
                            redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                    RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME, "false");
                        }
                    }
                    //LOG.info(String.format("【小程序获取云电梯状态】：%s",JsonUtil.toJSON(dto)));
                    if (StringUtils.isNotBlank(elevator.getIotDeviceId())&&
                            (dto == null || (StringUtils.isNotBlank(dto.getTimeout())))) {
                        if(dto != null && StringUtils.isNotBlank(dto.getTimeout())){
                            //清空该电梯设备缓存
                            redisService.delForDevice(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CACHE + deviceName);
                        }
                        //如果获取的电梯状态为null 或者超时时长有值，需要发送电梯状态上报控制指令
                        if(StringUtils.isBlank(redisService.get(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE +
                                deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl()))) {
                            Map<String, Object> control = new HashMap<>();
                            control.put("productKey", elevator.getIotProductKey());
                            if(StringUtils.isBlank(elevator.getVersion()) ||
                                    Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V")+1, elevator.getVersion().indexOf("V")+5)) < 1040) {
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("timeout", "300");
                                control.put("message", jsonObject.toJSONString());
                                control.put("topic", "/" + deviceName + (elevator.getIotVersion() == 1 ? "/user" : "") + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl());
                                controls.add(control);
                            }else{
                                JSONObject cmd = new JSONObject();
                                cmd.put("sourceFrom","itlong");
                                cmd.put("snr",0);
                                cmd.put("cmd",CloudElevatorIotOrderTypeEnum.REPORTCONTROLLER.getType());
                                JSONObject cmdChildChild = new JSONObject();
                                cmdChildChild.put("timeout","300");
                                cmd.put("data",cmdChildChild);
                                control.put("message", cmd.toJSONString());
                                control.put("topic", "/" + deviceName + (elevator.getIotVersion() == 1 ? "/user" : "") + IotCloudCtrlInstructEnum.DEVICECMD.getUrl());
                                cmdControls.add(control);
                            }
                            redisService.set(RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE + deviceName + IotCloudCtrlInstructEnum.DEVICEREPORTCTRL.getUrl(),
                                    RedisConstant.REDIS_IOT_CLOUD_ELEVATOR_STATE_CTRL_CACHE_TIME,"false");
                        }
                    }
                    if(StringUtils.isNotBlank(elevator.getIotDeviceId()) && dto!= null){
                        //返回获取的云电梯状态
                        MiniCloudElevatorRunStateVO runState = new MiniCloudElevatorRunStateVO();
                        runState.setDeviceUnique(deviceName);
                        runState.setDeviceName(elevator.getDeviceName());
                        runState.setFloorName(StringUtils.isBlank(elevator.getVersion()) ||
                                Integer.valueOf(elevator.getVersion().substring(elevator.getVersion().indexOf("V") + 1, elevator.getVersion().indexOf("V") + 5)) < 1040
                                ? iAppDeviceDao.getLogicFloorByFloorNum(dto.getFloor(), deviceName) : StringUtils.isNotBlank(dto.getFloor()) && !dto.getFloor().equals("0") ? dto.getFloor() : "-");
                        if(StringUtils.isNotBlank(runState.getFloorName())) {
                            //app状态为 1:上行  2:下行  3:停层  设备上报状态为：1:下行  2:上行 0：停层
                            if (dto.getUpDown().equals("1")) {
                                runState.setFloorStatus(2);
                            } else if (dto.getUpDown().equals("2")) {
                                runState.setFloorStatus(1);
                            } else {
                                runState.setFloorStatus(3);
                            }
                            //查询当前用户预约电梯状态
                            String operateStatus = null;
                            //如果电梯状态为开门状态,查询当前电梯是否为预约完成状态
                            Integer callId = iAppCloudElevatorCallStatusDao.checkSuccessState(userId, deviceName);
                            if (callId != null && callId > 0) {
                                //设置该条信息为已读
                                iAppCloudElevatorCallStatusDao.updateAppRead(callId);
                                operateStatus = CallElevatorOperateStateEnum.SUCCESS.getType().toString();
                            }
                            if (StringUtils.isBlank(operateStatus)) {
                                Map<String,Object> callInfo = iAppCloudElevatorCallStatusDao.getCallInfo(userId, deviceName);
                                //查询当前是否有预约该电梯设备
                                if (callInfo != null) {
                                    operateStatus = CallElevatorOperateStateEnum.CALLING.getType().toString();
                                    Integer fromFloor = Integer.valueOf(callInfo.get("fromFloor").toString());
                                    int realToFloor = Integer.valueOf(callInfo.get("realToFloor").toString());
                                    int realFromFloor = Integer.valueOf(callInfo.get("realFromFloor").toString());
                                    boolean isUp = false;
                                    boolean callController = false;
                                    if(realToFloor > realFromFloor){
                                        isUp = true;
                                    }
                                    if(isUp) {
                                        if(StringUtils.isNotBlank(upFloor)) {
                                            String[] upFloors = StringHandlerUtil.splitString(upFloor);
                                            for (String up : upFloors) {
                                                if (fromFloor.equals(Integer.valueOf(up))) {
                                                    callController = true;
                                                    break;
                                                }
                                            }
                                        }
                                    }else {
                                        if(StringUtils.isNotBlank(downFloor)){
                                            String[] downFloors = StringHandlerUtil.splitString(downFloor);
                                            for (String down : downFloors) {
                                                if (fromFloor.equals(Integer.valueOf(down))) {
                                                    callController = true;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                    if(callController){
                                        runState.setDisplayOther(0);
                                    }else{
                                        runState.setDisplayOther(1);
                                    }
                                } else {
                                    operateStatus = CallElevatorOperateStateEnum.CALL_NULL.getType().toString();
                                }
                            }
                            runState.setCallStatus(Integer.valueOf(operateStatus));
                            states.add(runState);
                        }
                    }
                }
            }
            //发送云电梯控制指令
            sendCloudElevatorMessage(controls,cmdControls);
            return states;
        }catch (Exception e){
            LOG.error("【云电梯获取实时状态异常】",e);
            throw e;
        }
    }


    /**
     * <desc>
     *      获取设备在iot中心的在线离线状态
     * </desc>
     *
     * @param devices
     * @author Jiaqi.X
     * @createDate 2019/04/04
     */
    private void sendSelectIotDeviceStatusMessage(String devices,String productKey) throws Exception {
        Map<String,Object> params = new HashMap<>();
        params.put("deviceUnique",devices);
        params.put("productKey",productKey);
        params.put("deviceOperateIotType", DeviceIotEnum.BATCH_GET_DEVICE_STATE.getCommandType());
        //把时间戳记录下来，消费的时候记得删除
        params.put("timestamp", (new Date()).getTime());
        JSONObject obj = new JSONObject();
        obj.put("data",params);
        messageSender.send(RabbitMQConstant.RABBITMQ_DEVICE_ELEVATOR_QUEUE, obj.toJSONString(),
                RabbitMQConstant.RABBITMQ_DEVICE_ELEVATOR_EXCHANGE, RabbitMQConstant.RABBITMQ_DEVICE_ELEVATOR_KEY);
    }

    /**
     * <desc>
     *      发布云电梯消息到iot中心
     * </desc>
     *
     * @param messages
     * @author Jiaqi.X
     * @createDate 2018/04/12
     */
    private void sendCloudElevatorMessage(List<Map<String,Object>> messages,List<Map<String,Object>> newMessages) throws Exception {
        if(!messages.isEmpty()){
            Map<String,Object> params = new HashMap<>();
            params.put("deviceOperateIotType", DeviceIotEnum.PUB_MESSAGE.getCommandType());
            params.put("devices",messages);
            params.put("timestamp", (new Date()).getTime());
            JSONObject obj = new JSONObject();
            obj.put("data",params);
            messageSender.send(RabbitMQConstant.RABBITMQ_IOT_PUB_QUEUE, obj.toJSONString(),
                    RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_IOT_PUB_KEY);
        }
        if(!newMessages.isEmpty()){
            Map<String,Object> params = new HashMap<>();
            params.put("deviceOperateIotType", DeviceIotEnum.PUB_MESSAGE.getCommandType());
            params.put("devices",newMessages);
            params.put("timestamp", (new Date()).getTime());
            JSONObject obj = new JSONObject();
            obj.put("data",params);
            messageSender.send(RabbitMQConstant.RABBITMQ_IOT_PUB_QUEUE, obj.toJSONString(),
                    RabbitMQConstant.RABBITMQ_IOT_PUB_EXCHANGE, RabbitMQConstant.RABBITMQ_IOT_PUB_KEY);
        }
    }

    /**
     * <desc>
     *      获取用户门禁设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppDoorDevicesVO> getDoorDevices(String userId,String projectId,Integer updateCache) throws Exception {
        //读取缓存信息
        List<AppDoorDevicesVO> list= (List<AppDoorDevicesVO>) redisService.decodeObject(
                RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId, new TypeReference<List<AppDoorDevicesVO>>() {});
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache == 1)) {
            //获取用户有权限的门禁设备机号
            List<Map<String,Object>> doorAuth = iAppDeviceDao.getDoorAuth(userId, projectId);
            AppEntranceOrCloudIntercomAuthVO doorVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.ENTRANCE.getType(),doorAuth);
            if (doorAuth!=null&&!doorAuth.isEmpty()) {
                String[] doors = doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]);
                if(doors !=null && doors.length > 0) {
                    list = iAppDeviceDao.getDoorDevices(userId, projectId, doors);
                    if (null != list && !list.isEmpty()) {
                        //解析排序值
                        String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                        for (AppDoorDevicesVO door : list) {
                            door.setDoorAuth("8");
                            door.setPosition(parseDeviceOrder(orders, door.getDeviceUnique()));
                            door.setValiTime(DateUtil.formatStringToDate(doorVO.getValiTime(), DateUtil.YYMMDDHHMMSS).getTime() + "");
                        }
                        redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                                RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                    }else{
                        redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                                RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                    }
                }else{
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            } else {
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      查询蓝牙外呼设备
     * </desc>
     *
     * @param deviceUniques
     * @return
     * @author Jiaqi.X
     * @createDate 2020/04/17
     */
    public List<AppOutCallDevicesVO> getOutCallDevices(Set<String> deviceUniques,String cardNum){
        List<AppOutCallDevicesVO> list = iAppDeviceDao.getOutCallDevices(deviceUniques);
        list.forEach(vo->{
            vo.setCardNum(cardNum);
        });
        return list;
    }

    /**
     * <desc>
     *      获取用户门禁设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppDoorDevicesVO> getTempDoorDevices(String userId,String projectId,Integer updateCache) throws Exception {
        //读取缓存信息
        List<AppDoorDevicesVO> list= new ArrayList<>();
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache == 1)) {
            //获取用户有权限的门禁设备机号
            List<Map<String,Object>> doorAuth = iAppDeviceDao.getTempDoorAuth(userId, projectId);
            AppEntranceOrCloudIntercomAuthVO doorVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.ENTRANCE.getType(),doorAuth);
            if (doorAuth!=null&&!doorAuth.isEmpty()) {
                String[] doors = doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]);
                if(doors !=null && doors.length > 0) {
                    list = iAppDeviceDao.getDoorDevices(userId, projectId, doors);
                    if (null != list && !list.isEmpty()) {
                        //解析排序值
                        String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                        for (AppDoorDevicesVO door : list) {
                            door.setDoorAuth("8");
                            door.setPosition(parseDeviceOrder(orders, door.getDeviceUnique()));
                            door.setValiTime(DateUtil.formatStringToDate(doorVO.getValiTime(), DateUtil.YYMMDDHHMMSS).getTime() + "");
                        }
                    }
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取用户门禁设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    private List<AppDoorDevicesVO> getSmartCardDoorDevices(String userId,String projectId,Integer updateCache) throws Exception {
        //读取缓存信息
        List<AppDoorDevicesVO> list= new ArrayList<>();
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache == 1)) {
            //获取用户有权限的门禁设备机号
            List<Map<String,Object>> doorAuth = iAppDeviceDao.getSmartCardDoorAuth(userId, projectId);
            AppEntranceOrCloudIntercomAuthVO doorVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.ENTRANCE.getType(),doorAuth);
            if (doorAuth!=null&&!doorAuth.isEmpty()) {
                String[] doors = doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]);
                if(doors !=null && doors.length > 0) {
                    list = iAppDeviceDao.getDoorDevices(userId, projectId, doors);
                    if (null != list && !list.isEmpty()) {
                        //解析排序值
                        String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                        for (AppDoorDevicesVO door : list) {
                            door.setDoorAuth("8");
                            door.setPosition(parseDeviceOrder(orders, door.getDeviceUnique()));
                            door.setValiTime(DateUtil.formatStringToDate(doorVO.getValiTime(), DateUtil.YYMMDDHHMMSS).getTime() + "");
                        }
                    }
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }


    /**
     * <desc>
     *     根据设备序列号查询绑定控制器
     * </desc>
     *
     * @param elevatorDeviceUnique
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/28
     */
    @Override
    public Map<String,Object>getControllerDeviceUniqueByElevatorDeviceUnique(String elevatorDeviceUnique){
        return iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUnique(elevatorDeviceUnique);
    }

    /**
     * <desc>
     *     更新个人设备排序值
     * </desc>
     *
     * @param userId 用户编号
     * @param projectId 项目编号
     * @param deviceUniques 设备编号逗号分隔
     * @return
     * @author Qiang.S
     * @createDate 2019/08/07
     */
    @Override
    public Integer uploadDeviceOrder(String userId,String projectId,String deviceUniques,String deviceType){
        if ("2".equals(deviceType)) {
            return iAppDeviceDao.uploadElevatorOrder(userId,projectId,deviceUniques);
        } else if ("3".equals(deviceType)) {
            return iAppDeviceDao.uploadElevatorControllerOrder(userId,projectId,deviceUniques);
        } else {
            return iAppDeviceDao.uploadDeviceOrder(userId, projectId, deviceUniques);
        }
    }

    /**
     * <desc>
     *     获取个人设备排序信息
     * </desc>
     *
     * @param userId 用户编号
     * @param projectId 项目编号
     * @return
     * @author Qiang.S
     * @createDate 2019/08/07
     */
    @Override
    public String getUserDeviceOrder(String userId, String projectId){
        return iAppDeviceDao.getUserDeviceOrder(userId, projectId);
    }

    /**
     * <desc>
     *      获取个人电梯设备排序信息
     * </desc>
     *
     * @param userId    用户编号
     * @param projectId 项目编号
     * @return 个人电梯设备排序信息
     * @author wangzhi
     * @createDate 2019/10/09
     */
    @Override
    public String getUserElevatorOrder(String userId, String projectId) {
        return iAppDeviceDao.getUserElevatorOrder(userId,projectId);
    }

    /**
     * <desc>
     *      获取用户常用楼层
     * </desc>
     *
     * @param userId    用户编号
     * @param projectId 项目编号
     * @return 用户常用楼层
     * @author wangzhi
     * @createDate 2019/10/11
     */
    @Override
    public String getUserCommonFloor(String userId, String projectId) throws Exception {
        return iAppDeviceDao.getUserCommonFloor(userId, projectId);
    }

    /**
     * <desc>
     *      获取用户常用公共楼层
     * </desc>
     *
     * @param userId 用户编号
     * @param projectId 项目编号
     * @return 用户常用公共楼层
     * @author pengwei
     * @createDate 2020-11-13
     */
    @Override
    public String getUserPublicFloor(String userId, String projectId) throws Exception {
        return iAppDeviceDao.getUserPublicFloor(userId, projectId);
    }

    /**
     * <desc>
     *      获取用户电梯设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppFloorDevicesVO> getFloorDevices(String userId, String projectId,Integer updateCache) {
        List<AppFloorDevicesVO> list= (List<AppFloorDevicesVO>) redisService.decodeObject(
                RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE+userId+projectId,new TypeReference<List<AppFloorDevicesVO>>(){});
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache==1)) {
            //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
            List<AppElevatorAuthDTO> auth = iAppDeviceDao.getFloorAuth(userId, projectId);
            if (auth.isEmpty()) {
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                return new ArrayList<>();
            }
            AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
            String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
            List<String> controllerDevices = new ArrayList<>();
            for(String device : devices){
                controllerDevices.add(projectId+"1"+device);
            }
            if (devices.length > 0) {
                list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
                //将筛选的用户电梯权限详情放入用户权限信息
                if (null != list && !list.isEmpty()) {
                    //解析设备排序值
                    String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                    floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                        AppFloorDevicesVO floorDevice = list.get(j);
//                        list.forEach(floorDevice -> {
                        //设置设备排序值
                        floorDevice.setPosition(parseDeviceOrder(orders, floorDevice.getDeviceUnique()));
                        //检索电梯是否是云电梯，如果是则查询是否绑定控制器
                        if (StringUtils.isNotBlank(floorDevice.getLiftType()) && !floorDevice.getLiftType().equals("1")) {
                            Map<String, Object> controlls = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(floorDevice.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                            if (controlls != null && controlls.get("groupConId") != null) {
                                if(!controlls.get("status").toString().equals("1")){
                                    list.remove(j);
                                    continue floor;
                                }
                                floorDevice.setGroupConId(controlls.get("groupConId").toString());
                                floorDevice.setRelatedDeviceId(controlls.get("deviceUnique").toString());
                            }
                        }
                        //设置楼层权限
                        elevator.getElevatorAuth().forEach(authInfo -> {
                            if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                                List<String> lifeFloors = new ArrayList<>();
                                //获取电梯起始楼层及结束楼层
                                Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                                if (minAndMaxFloor != null) {
                                    Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                    Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                    if (startFloor != null) {
                                        String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                        for (String f : tempLifeFloor) {
                                            if (Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor) {
                                                lifeFloors.add(f);
                                            }
                                        }
                                        authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                    }
                                }
                                //设置常用居住楼层
                                floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                                //设置已选常用公共楼层
                                floorDevice.setCommonChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getCommonChoiceFloor()));
                                //设置已选常用居住楼层
                                floorDevice.setLiveChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveChoiceFloor()));
                                //设置楼层权限
                                floorDevice.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors(authInfo.getLiveFloor())).toUpperCase());
                                Set<String> floorSet = new HashSet<String>();
                                //设置待选居住楼层名称
                                if (StringUtils.isNotBlank(floorDevice.getLiveFloor())) {
                                    //查询电梯的外呼信息
                                    List<String> lf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getLiveFloor()));
                                    for(String l : lf){
                                        floorSet.add(l);
                                    }
                                    floorDevice.setLiveFloor(iAppDeviceDao.getLiveFloor(lf, floorDevice.getDeviceUnique()));
                                    floorDevice.setLiveLogicalFloor(iAppDeviceDao.getLogicalFloor(lf, floorDevice.getDeviceUnique()));
                                    if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                        //设置公共楼层
                                        List<String> commonFloors = iAppDeviceDao.getNaturalFloorByFloorNum(StringHandlerUtil.splitString(floorDevice.getCommonFloor()), floorDevice.getDeviceUnique());
                                        if (commonFloors != null) {
                                              //如果常用楼层权限包括公共楼层，此处不能再剔除
                                              // 因为前端 需要 公共楼层全量列表  作为  判断是否有
                                              // 权限重叠现象（公共楼层有1楼，然后常用楼层权限也有1楼）的依据
//                                            for (int i = commonFloors.size(); i > 0; i--) {
//                                                Integer n = i;
//                                                Optional<String> findOne = lf.stream().filter(floorNum -> floorNum.equals(commonFloors.get(n - 1))).findFirst();
//                                                if (findOne.isPresent()) {
//                                                    commonFloors.remove(i - 1);
//                                                    continue;
//                                                }
//                                            }
                                            for(String c : commonFloors){
                                                floorSet.add(c);
                                            }
                                            floorDevice.setCommonFloor(StringUtils.join(commonFloors.toArray(new String[commonFloors.size()]), ","));

                                        }
                                        //设置待选常用公共楼层名称
                                        if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                            floorDevice.setCommonLogicalFloor(iAppDeviceDao.getLogicalFloor(
                                                    Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor())), floorDevice.getDeviceUnique()));
                                        }
                                    }
                                }
                                //设置常用公共楼层名称
                                if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                    List<String> cf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor()));
                                    floorDevice.setCommonLogicalFloor(iAppDeviceDao.getCommonLogicalFloor(cf, floorDevice.getDeviceUnique()));
                                }
                                if(!floorSet.isEmpty()) {
                                    Map<String, Object> floors = iAppDeviceDao.getOrderFloors(floorSet, floorDevice.getDeviceUnique());
                                    floorDevice.setFloors(StringHandlerUtil.getNullOrStringForObject(floors.get("floors")));
                                    floorDevice.setFloorsName(StringHandlerUtil.getNullOrStringForObject(floors.get("floorsName")));
                                    Map<String,Object> outCalls = iAppDeviceDao.getOutCallDevicesByElevatorAndFloor(floorDevice.getDeviceUnique(),
                                            floorSet);
                                    if(outCalls!=null && outCalls.get("blueToothDevices")!=null){
                                        floorDevice.setBlueToothDevices(outCalls.get("blueToothDevices").toString());
                                        floorDevice.setBlueToothFloor(outCalls.get("blueToothFloor").toString());
                                    }
                                }
                                //设置过期时间
                                try {
                                    floorDevice.setValiTime(DateUtil.formatStringToDate(
                                            StringHandlerUtil.filterLastComma(elevator.getVailTime()), DateUtil.YYMMDDHHMMSS).getTime() + "");
                                } catch (ParseException e) {

                                }
                            }
                        });
//                        });
                    }
                    //设置缓存
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                }else{
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            }else{
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME,  new ArrayList<>());
            }
        }
        return list == null ? new ArrayList<>() : list;
    }



    /**
     * <desc>
     *      获取用户电梯设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppFloorDevicesVO> getTempFloorDevices(String userId, String projectId,Integer updateCache) {
        List<AppFloorDevicesVO> list= new ArrayList<>();
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
            //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
        List<AppElevatorAuthDTO> auth = iAppDeviceDao.getTempFloorAuth(userId, projectId);
        if (auth.isEmpty()) {
            return new ArrayList<>();
        }
        AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
        String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
        List<String> controllerDevices = new ArrayList<>();
        for(String device : devices){
            controllerDevices.add(projectId+"1"+device);
        }
        if (devices.length > 0) {
            list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
            //将筛选的用户电梯权限详情放入用户权限信息
            if (null != list && !list.isEmpty()) {
                //解析设备排序值
                String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                    AppFloorDevicesVO floorDevice = list.get(j);
//                        list.forEach(floorDevice -> {
                    //设置设备排序值
                    floorDevice.setPosition(parseDeviceOrder(orders, floorDevice.getDeviceUnique()));
                    //检索电梯是否是云电梯，如果是则查询是否绑定控制器
                    if (StringUtils.isNotBlank(floorDevice.getLiftType()) && !floorDevice.getLiftType().equals("1")) {
                        Map<String, Object> controlls = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(floorDevice.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                        if (controlls != null && controlls.get("groupConId") != null) {
                            if(!controlls.get("status").toString().equals("1")){
                                list.remove(j);
                                continue floor;
                            }
                            floorDevice.setGroupConId(controlls.get("groupConId").toString());
                            floorDevice.setRelatedDeviceId(controlls.get("deviceUnique").toString());
                        }
                    }
                    //设置楼层权限
                    elevator.getElevatorAuth().forEach(authInfo -> {
                        if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                            List<String> lifeFloors = new ArrayList<>();
                            //获取电梯起始楼层及结束楼层
                            Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                            if (minAndMaxFloor != null) {
                                Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                if (startFloor != null) {
                                    String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                    for (String f : tempLifeFloor) {
                                        if (Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor) {
                                            lifeFloors.add(f);
                                        }
                                    }
                                    authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                }
                            }
                            //设置常用居住楼层
                            floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                            //设置已选常用公共楼层
                            floorDevice.setCommonChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getCommonChoiceFloor()));
                            //设置已选常用居住楼层
                            floorDevice.setLiveChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveChoiceFloor()));
                            //设置楼层权限
                            floorDevice.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors(authInfo.getLiveFloor())).toUpperCase());
                            //设置待选居住楼层名称
                            if (StringUtils.isNotBlank(floorDevice.getLiveFloor())) {
                                List<String> lf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getLiveFloor()));
                                floorDevice.setLiveLogicalFloor(iAppDeviceDao.getLogicalFloor(lf, floorDevice.getDeviceUnique()));
                                if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                    //设置公共楼层
                                    List<String> commonFloors = iAppDeviceDao.getNaturalFloorByFloorNum(StringHandlerUtil.splitString(floorDevice.getCommonFloor()), floorDevice.getDeviceUnique());
                                    if (commonFloors != null)
                                        for (int i = commonFloors.size(); i > 0; i--) {
                                            Integer n = i;
                                            Optional<String> findOne = lf.stream().filter(floorNum -> floorNum.equals(commonFloors.get(n - 1))).findFirst();
                                            if (findOne.isPresent()) {
                                                commonFloors.remove(i - 1);
                                            }
                                        }
                                    floorDevice.setCommonFloor(StringUtils.join(commonFloors.toArray(new String[commonFloors.size()]), ","));
                                    //设置待选常用公共楼层名称
                                    if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                        floorDevice.setCommonLogicalFloor(iAppDeviceDao.getLogicalFloor(
                                                Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor())), floorDevice.getDeviceUnique()));
                                    }
                                }
                            }
                            //设置常用公共楼层名称
                            if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                List<String> cf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor()));
                                floorDevice.setCommonLogicalFloor(iAppDeviceDao.getCommonLogicalFloor(cf, floorDevice.getDeviceUnique()));
                            }
                            //设置过期时间
                            try {
                                floorDevice.setValiTime(DateUtil.formatStringToDate(
                                        StringHandlerUtil.filterLastComma(elevator.getVailTime()), DateUtil.YYMMDDHHMMSS).getTime() + "");
                            } catch (ParseException e) {
                            }
                        }
                    });
//                        });
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取用户电梯设备列表 仅供用于合景泰富非标查询（需查出用户所拥有权限楼层所对应房间的正背门信息）
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Juguang.S
     * @createDate 2021/03/10
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppFloorDevicesVO> getFloorDevicesByNoStardard(String userId, String projectId,Integer updateCache) {
//        List<AppFloorDevicesVO> list= (List<AppFloorDevicesVO>) redisService.decodeObject(
//                RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE_BY_NO_STARDARD+userId+projectId,new TypeReference<List<AppFloorDevicesVO>>(){});
        List<AppFloorDevicesVO> list= null;
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache==1)) {
            //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
            List<AppElevatorAuthDTO> auth = iAppDeviceDao.getFloorAuth(userId, projectId);
            if (auth.isEmpty()) {
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE_BY_NO_STARDARD + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                return new ArrayList<>();
            }
            AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
            String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
            List<String> controllerDevices = new ArrayList<>();
            for(String device : devices){
                controllerDevices.add(projectId+"1"+device);
            }
            if (devices.length > 0) {
                list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
                //将筛选的用户电梯权限详情放入用户权限信息
                if (null != list && !list.isEmpty()) {
                    //解析设备排序值
                    String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                    floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                        AppFloorDevicesVO floorDevice = list.get(j);
//                        list.forEach(floorDevice -> {
                        //设置设备排序值
                        floorDevice.setPosition(parseDeviceOrder(orders, floorDevice.getDeviceUnique()));
                        //检索电梯是否是云电梯，如果是则查询是否绑定控制器
                        if (StringUtils.isNotBlank(floorDevice.getLiftType()) && !floorDevice.getLiftType().equals("1")) {
                            Map<String, Object> controlls = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(floorDevice.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                            if (controlls != null && controlls.get("groupConId") != null) {
                                if(!controlls.get("status").toString().equals("1")){
                                    list.remove(j);
                                    continue floor;
                                }
                                floorDevice.setGroupConId(controlls.get("groupConId").toString());
                                floorDevice.setRelatedDeviceId(controlls.get("deviceUnique").toString());
                            }
                        }
                        //设置楼层权限
                        elevator.getElevatorAuth().forEach(authInfo -> {
                            if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                                List<String> lifeFloors = new ArrayList<>();
                                //获取电梯起始楼层及结束楼层
                                Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                                if (minAndMaxFloor != null) {
                                    Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                    Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                    if (startFloor != null) {
                                        String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                        for (String f : tempLifeFloor) {
                                            if (Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor) {
                                                lifeFloors.add(f);
                                            }
                                        }
                                        authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                    }
                                }
                                //设置常用居住楼层
                                floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                                //设置已选常用公共楼层
                                floorDevice.setCommonChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getCommonChoiceFloor()));
                                //设置已选常用居住楼层
                                floorDevice.setLiveChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveChoiceFloor()));
                                //设置楼层权限
                                floorDevice.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors(authInfo.getLiveFloor())).toUpperCase());
                                Set<String> floorSet = new HashSet<String>();
                                //设置待选居住楼层名称
                                if (StringUtils.isNotBlank(floorDevice.getLiveFloor())) {
                                    //查询电梯的外呼信息
                                    List<String> lf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getLiveFloor()));
                                    for(String l : lf){
                                        floorSet.add(l);
                                    }
                                    floorDevice.setLiveFloor(iAppDeviceDao.getLiveFloor(lf, floorDevice.getDeviceUnique()));

                                    //TODO 此处处理用户在指定电梯楼层权限所对应的房间的正背门逻辑
                                    String[] liveFloorArr = StringHandlerUtil.splitString(floorDevice.getLiveFloor());
                                    List<String> floorNum = new ArrayList<>();
                                    StringBuffer mainDoor = new StringBuffer();
                                    StringBuffer backDoor = new StringBuffer();
                                    Set<String> mainSet = new HashSet<>();
                                    Set<String> backSet = new HashSet<>();
                                    String mainDoorStr = "";
                                    String backDoorStr = "";
                                    List<Map<String,Object>> mapResult = iAppDeviceDao.getFloorNum(lf, floorDevice.getDeviceUnique());
                                    for(Map<String,Object> map : mapResult){
                                        floorNum.add(map.get("floorNum").toString());
                                    }
                                    List<Map<String,Object>> LiftDoorTypeArr = iAppDeviceDao.getRoomLiftDoorType(floorNum, floorDevice.getDeviceUnique(),floorDevice.getProjectId(),userId);
                                    //此处组装权限楼层所对应的正背门逻辑
                                    for(Map<String,Object> map : mapResult){
                                        for(Map<String,Object> liftDoorMap : LiftDoorTypeArr){
                                            if(map.get("floorNum").toString().equals(liftDoorMap.get("roomNum").toString().replace(".0",""))){
                                                if(liftDoorMap.get("liftDoorType").toString().equals("1")){
                                                    mainSet.add(map.get("naturalFloor").toString());
                                                }else{
                                                    backSet.add(map.get("naturalFloor").toString());
                                                }
                                                continue;
                                            }
                                        }
                                    }
                                    if(mainSet.size()>0){
                                        floorDevice.setMainFloor(StringUtils.join(mainSet.toArray(),","));
                                    }
                                    if(backSet.size()>0){
                                        floorDevice.setBackFloor(StringUtils.join(backSet.toArray(),","));
                                    }
                                    floorDevice.setLiveLogicalFloor(iAppDeviceDao.getLogicalFloor(lf, floorDevice.getDeviceUnique()));
                                    if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                        //设置公共楼层
                                        List<String> commonFloors = iAppDeviceDao.getNaturalFloorByFloorNum(StringHandlerUtil.splitString(floorDevice.getCommonFloor()), floorDevice.getDeviceUnique());
                                        if (commonFloors != null) {
                                            //如果常用楼层权限包括公共楼层，此处不能再剔除
                                            // 因为前端 需要 公共楼层全量列表  作为  判断是否有
                                            // 权限重叠现象（公共楼层有1楼，然后常用楼层权限也有1楼）的依据
//                                            for (int i = commonFloors.size(); i > 0; i--) {
//                                                Integer n = i;
//                                                Optional<String> findOne = lf.stream().filter(floorNum -> floorNum.equals(commonFloors.get(n - 1))).findFirst();
//                                                if (findOne.isPresent()) {
//                                                    commonFloors.remove(i - 1);
//                                                    continue;
//                                                }
//                                            }
                                            for(String c : commonFloors){
                                                floorSet.add(c);
                                            }
                                            floorDevice.setCommonFloor(StringUtils.join(commonFloors.toArray(new String[commonFloors.size()]), ","));

                                        }
                                        //设置待选常用公共楼层名称
                                        if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                            floorDevice.setCommonLogicalFloor(iAppDeviceDao.getLogicalFloor(
                                                    Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor())), floorDevice.getDeviceUnique()));
                                        }
                                    }
                                }
                                //设置常用公共楼层名称
                                if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                    List<String> cf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor()));
                                    floorDevice.setCommonLogicalFloor(iAppDeviceDao.getCommonLogicalFloor(cf, floorDevice.getDeviceUnique()));
                                }
                                if(!floorSet.isEmpty()) {
                                    Map<String, Object> floors = iAppDeviceDao.getOrderFloors(floorSet, floorDevice.getDeviceUnique());
                                    floorDevice.setFloors(StringHandlerUtil.getNullOrStringForObject(floors.get("floors")));
                                    floorDevice.setFloorsName(StringHandlerUtil.getNullOrStringForObject(floors.get("floorsName")));
                                    Map<String,Object> outCalls = iAppDeviceDao.getOutCallDevicesByElevatorAndFloor(floorDevice.getDeviceUnique(),
                                            floorSet);
                                    if(outCalls!=null && outCalls.get("blueToothDevices")!=null){
                                        floorDevice.setBlueToothDevices(outCalls.get("blueToothDevices").toString());
                                        floorDevice.setBlueToothFloor(outCalls.get("blueToothFloor").toString());
                                    }
                                }
                                //设置过期时间
                                try {
                                    floorDevice.setValiTime(DateUtil.formatStringToDate(
                                            StringHandlerUtil.filterLastComma(elevator.getVailTime()), DateUtil.YYMMDDHHMMSS).getTime() + "");
                                } catch (ParseException e) {

                                }
                            }
                        });
//                        });
                    }
                    //设置缓存
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE_BY_NO_STARDARD + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                }else{
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE_BY_NO_STARDARD + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            }else{
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_CACHE_BY_NO_STARDARD + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME,  new ArrayList<>());
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取用户一卡通电梯设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    private List<AppFloorDevicesVO> getAddressFloorDevices(String userId, String projectId,Integer updateCache) {
        List<AppFloorDevicesVO> list= new ArrayList<>();
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
        List<AppElevatorAuthDTO> auth = iAppDeviceDao.getAddressAuth(userId, projectId);
        if (auth.isEmpty()) {
            return new ArrayList<>();
        }
        AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
        String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
        List<String> controllerDevices = new ArrayList<>();
        for(String device : devices){
            controllerDevices.add(projectId+"1"+device);
        }
        if (devices.length > 0) {
            list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
            //将筛选的用户电梯权限详情放入用户权限信息
            if (null != list && !list.isEmpty()) {
                //解析设备排序值
                String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                    AppFloorDevicesVO floorDevice = list.get(j);
//                        list.forEach(floorDevice -> {
                    //设置设备排序值
                    floorDevice.setPosition(parseDeviceOrder(orders, floorDevice.getDeviceUnique()));
                    //检索电梯是否是云电梯，如果是则查询是否绑定控制器
                    if (StringUtils.isNotBlank(floorDevice.getLiftType()) && !floorDevice.getLiftType().equals("1")) {
                        Map<String, Object> controlls = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(floorDevice.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                        if (controlls != null && controlls.get("groupConId") != null) {
                            if(!controlls.get("status").toString().equals("1")){
                                list.remove(j);
                                continue floor;
                            }
                            floorDevice.setGroupConId(controlls.get("groupConId").toString());
                            floorDevice.setRelatedDeviceId(controlls.get("deviceUnique").toString());
                        }
                    }
                    //设置楼层权限
                    elevator.getElevatorAuth().forEach(authInfo -> {
                        if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                            List<String> lifeFloors = new ArrayList<>();
                            //获取电梯起始楼层及结束楼层
                            Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                            if (minAndMaxFloor != null) {
                                Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                if (startFloor != null) {
                                    String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                    for (String f : tempLifeFloor) {
                                        if (Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor) {
                                            lifeFloors.add(f);
                                        }
                                    }
                                    authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                }
                            }
                            //设置常用居住楼层
                            floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                            //设置已选常用公共楼层
                            floorDevice.setCommonChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getCommonChoiceFloor()));
                            //设置已选常用居住楼层
                            floorDevice.setLiveChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveChoiceFloor()));
                            //设置楼层权限
                            floorDevice.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors(authInfo.getLiveFloor())).toUpperCase());
                            //设置待选居住楼层名称
                            if (StringUtils.isNotBlank(floorDevice.getLiveFloor())) {
                                List<String> lf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getLiveFloor()));
                                floorDevice.setLiveLogicalFloor(iAppDeviceDao.getLogicalFloor(lf, floorDevice.getDeviceUnique()));
                                if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                    //设置公共楼层
                                    List<String> commonFloors = iAppDeviceDao.getNaturalFloorByFloorNum(StringHandlerUtil.splitString(floorDevice.getCommonFloor()), floorDevice.getDeviceUnique());
                                    if (commonFloors != null)
                                        for (int i = commonFloors.size(); i > 0; i--) {
                                            Integer n = i;
                                            Optional<String> findOne = lf.stream().filter(floorNum -> floorNum.equals(commonFloors.get(n - 1))).findFirst();
                                            if (findOne.isPresent()) {
                                                commonFloors.remove(i - 1);
                                            }
                                        }
                                    floorDevice.setCommonFloor(StringUtils.join(commonFloors.toArray(new String[commonFloors.size()]), ","));
                                    //设置待选常用公共楼层名称
                                    if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                        floorDevice.setCommonLogicalFloor(iAppDeviceDao.getLogicalFloor(
                                                Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor())), floorDevice.getDeviceUnique()));
                                    }
                                }
                            }
                            //设置常用公共楼层名称
                            if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                List<String> cf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor()));
                                floorDevice.setCommonLogicalFloor(iAppDeviceDao.getCommonLogicalFloor(cf, floorDevice.getDeviceUnique()));
                            }
                            //设置过期时间
                            try {
                                floorDevice.setValiTime(DateUtil.formatStringToDate(
                                        StringHandlerUtil.filterLastComma(elevator.getVailTime()), DateUtil.YYMMDDHHMMSS).getTime() + "");
                            } catch (ParseException e) {
                            }
                        }
                    });
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取用户一卡通电梯设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    private List<AppFloorDevicesVO> getSmartCardFloorDevices(String userId, String projectId,Integer updateCache) {
        List<AppFloorDevicesVO> list= new ArrayList<>();
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
        List<AppElevatorAuthDTO> auth = iAppDeviceDao.getSmartCardFloorAuth(userId, projectId);
        if (auth.isEmpty()) {
            return new ArrayList<>();
        }
        AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
        String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
        List<String> controllerDevices = new ArrayList<>();
        for(String device : devices){
            controllerDevices.add(projectId+"1"+device);
        }
        if (devices.length > 0) {
            list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
            //将筛选的用户电梯权限详情放入用户权限信息
            if (null != list && !list.isEmpty()) {
                //解析设备排序值
                String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                    AppFloorDevicesVO floorDevice = list.get(j);
//                        list.forEach(floorDevice -> {
                    //设置设备排序值
                    floorDevice.setPosition(parseDeviceOrder(orders, floorDevice.getDeviceUnique()));
                    //检索电梯是否是云电梯，如果是则查询是否绑定控制器
                    if (StringUtils.isNotBlank(floorDevice.getLiftType()) && !floorDevice.getLiftType().equals("1")) {
                        Map<String, Object> controlls = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(floorDevice.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                        if (controlls != null && controlls.get("groupConId") != null) {
                            if(!controlls.get("status").toString().equals("1")){
                                list.remove(j);
                                continue floor;
                            }
                            floorDevice.setGroupConId(controlls.get("groupConId").toString());
                            floorDevice.setRelatedDeviceId(controlls.get("deviceUnique").toString());
                        }
                    }
                    //设置楼层权限
                    elevator.getElevatorAuth().forEach(authInfo -> {
                        if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                            List<String> lifeFloors = new ArrayList<>();
                            //获取电梯起始楼层及结束楼层
                            Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                            if (minAndMaxFloor != null) {
                                Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                if (startFloor != null) {
                                    String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                    for (String f : tempLifeFloor) {
                                        if (Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor) {
                                            lifeFloors.add(f);
                                        }
                                    }
                                    authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                }
                            }
                            //设置常用居住楼层
                            floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                            //设置已选常用公共楼层
                            floorDevice.setCommonChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getCommonChoiceFloor()));
                            //设置已选常用居住楼层
                            floorDevice.setLiveChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveChoiceFloor()));
                            //设置楼层权限
                            floorDevice.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors(authInfo.getLiveFloor())).toUpperCase());
                            //设置待选居住楼层名称
                            if (StringUtils.isNotBlank(floorDevice.getLiveFloor())) {
                                List<String> lf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getLiveFloor()));
                                floorDevice.setLiveLogicalFloor(iAppDeviceDao.getLogicalFloor(lf, floorDevice.getDeviceUnique()));
                                if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                    //设置公共楼层
                                    List<String> commonFloors = iAppDeviceDao.getNaturalFloorByFloorNum(StringHandlerUtil.splitString(floorDevice.getCommonFloor()), floorDevice.getDeviceUnique());
                                    if (commonFloors != null)
                                        for (int i = commonFloors.size(); i > 0; i--) {
                                            Integer n = i;
                                            Optional<String> findOne = lf.stream().filter(floorNum -> floorNum.equals(commonFloors.get(n - 1))).findFirst();
                                            if (findOne.isPresent()) {
                                                commonFloors.remove(i - 1);
                                            }
                                        }
                                    floorDevice.setCommonFloor(StringUtils.join(commonFloors.toArray(new String[commonFloors.size()]), ","));
                                    //设置待选常用公共楼层名称
                                    if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                        floorDevice.setCommonLogicalFloor(iAppDeviceDao.getLogicalFloor(
                                                Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor())), floorDevice.getDeviceUnique()));
                                    }
                                }
                            }
                            //设置常用公共楼层名称
                            if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                List<String> cf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor()));
                                floorDevice.setCommonLogicalFloor(iAppDeviceDao.getCommonLogicalFloor(cf, floorDevice.getDeviceUnique()));
                            }
                            //设置过期时间
                            try {
                                floorDevice.setValiTime(DateUtil.formatStringToDate(
                                        StringHandlerUtil.filterLastComma(elevator.getVailTime()), DateUtil.YYMMDDHHMMSS).getTime() + "");
                            } catch (ParseException e) {
                            }
                        }
                    });
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取用户电梯设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @param arrearsType 是否限制用户楼层权限 8是
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppFloorDevicesVO> getFloorDevicesForPad(String userId, String projectId,Integer updateCache,Integer arrearsType) {
        List<AppFloorDevicesVO> list= (List<AppFloorDevicesVO>) redisService.decodeObject(
                RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_PAD_CACHE+userId+projectId,new TypeReference<List<AppFloorDevicesVO>>(){});
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache==1)) {
            //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
            List<AppElevatorAuthDTO> auth = iAppDeviceDao.getFloorAuth(userId, projectId);
            if (auth.isEmpty()) {
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_PAD_CACHE + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                return new ArrayList<>();
            }
            AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
            String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
            List<String> controllerDevices = new ArrayList<>();
            for(String device : devices){
                controllerDevices.add(projectId+"1"+device);
            }
            if (devices.length > 0) {
                list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
                //将筛选的用户电梯权限详情放入用户权限信息
                if (null != list && !list.isEmpty()) {
                    //解析设备排序值
                    String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                    floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                        AppFloorDevicesVO floorDevice = list.get(j);
//                        list.forEach(floorDevice -> {
                        //设置设备排序值
                        floorDevice.setPosition(parseDeviceOrder(orders, floorDevice.getDeviceUnique()));
                        //检索电梯是否是云电梯，如果是则查询是否绑定控制器
                        if (StringUtils.isNotBlank(floorDevice.getLiftType()) && !floorDevice.getLiftType().equals("1")) {
                            Map<String, Object> controlls = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(floorDevice.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                            if (controlls != null && controlls.get("groupConId") != null) {
                                if(!controlls.get("status").toString().equals("1")){
                                    list.remove(j);
                                    continue floor;
                                }
                                floorDevice.setGroupConId(controlls.get("groupConId").toString());
                                floorDevice.setRelatedDeviceId(controlls.get("deviceUnique").toString());
                            }
                        }
                        //设置楼层权限
                        elevator.getElevatorAuth().forEach(authInfo -> {
                            if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                                List<String> lifeFloors = new ArrayList<>();
                                //获取电梯起始楼层及结束楼层
                                Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                                if (minAndMaxFloor != null) {
                                    Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                    Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                    //获取用户在该电梯楼栋未欠费的房间
                                    List<String> noArrearsFloor = null;
                                    if(arrearsType == 8){
                                        String roomNums = iAppDeviceDao.getNoArrearsRoomNumsByUserIdAndElevator(floorDevice.getDeviceUnique(),userId,projectId);
                                        String[] noArrearsRoomNums = StringHandlerUtil.splitString(roomNums);
                                        if(noArrearsRoomNums != null && noArrearsRoomNums.length > 0){
                                            for(int i=0;i<noArrearsRoomNums.length;i++){
                                                noArrearsRoomNums[i] = Integer.valueOf(noArrearsRoomNums[i].substring(0,2)).toString();
                                            }
                                            noArrearsFloor = iAppDeviceDao.getNoArrearsNaturalFloor(noArrearsRoomNums,floorDevice.getDeviceUnique(),startFloor,endFloor);
                                        }else{
                                            noArrearsFloor = new ArrayList<String>();
                                        }
                                    }
                                    if (startFloor != null) {
                                        String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                        for (String f : tempLifeFloor) {
                                            if ((Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor)&&(arrearsType!=8
                                                    ||(noArrearsFloor!=null && noArrearsFloor.stream().filter(noFloor->noFloor.equals(f)).findFirst().isPresent())||noArrearsFloor.isEmpty())) {
                                                lifeFloors.add(f);
                                            }
                                        }
                                        authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                    }
                                }
                                //设置常用居住楼层
                                floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                                //设置已选常用公共楼层
                                floorDevice.setCommonChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getCommonChoiceFloor()));
                                //设置已选常用居住楼层
                                floorDevice.setLiveChoiceFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveChoiceFloor()));
                                //设置楼层权限
                                floorDevice.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors(authInfo.getLiveFloor())).toUpperCase());
                                //设置待选居住楼层名称
                                if (StringUtils.isNotBlank(floorDevice.getLiveFloor())) {
                                    List<String> lf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getLiveFloor()));
                                    floorDevice.setLiveLogicalFloor(iAppDeviceDao.getLogicalFloor(lf, floorDevice.getDeviceUnique()));
                                    if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                        //设置公共楼层
                                        List<String> commonFloors = iAppDeviceDao.getNaturalFloorByFloorNum(StringHandlerUtil.splitString(floorDevice.getCommonFloor()), floorDevice.getDeviceUnique());
                                        if (commonFloors != null)
                                            for (int i = commonFloors.size(); i > 0; i--) {
                                                Integer n = i;
                                                Optional<String> findOne = lf.stream().filter(floorNum -> floorNum.equals(commonFloors.get(n - 1))).findFirst();
                                                if (findOne.isPresent()) {
                                                    commonFloors.remove(i - 1);
                                                }
                                            }
                                        floorDevice.setCommonFloor(StringUtils.join(commonFloors.toArray(new String[commonFloors.size()]), ","));
                                        //设置待选常用公共楼层名称
                                        if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                            floorDevice.setCommonLogicalFloor(iAppDeviceDao.getLogicalFloor(
                                                    Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor())), floorDevice.getDeviceUnique()));
                                        }
                                    }
                                }
                                //设置常用公共楼层名称
                                if (StringUtils.isNotBlank(floorDevice.getCommonFloor())) {
                                    List<String> cf = Arrays.asList(StringHandlerUtil.splitString(floorDevice.getCommonFloor()));
                                    floorDevice.setCommonLogicalFloor(iAppDeviceDao.getCommonLogicalFloor(cf, floorDevice.getDeviceUnique()));
                                }
                                //设置过期时间
                                try {
                                    floorDevice.setValiTime(DateUtil.formatStringToDate(
                                            StringHandlerUtil.filterLastComma(elevator.getVailTime()), DateUtil.YYMMDDHHMMSS).getTime() + "");
                                } catch (ParseException e) {
                                }
                            }
                        });
//                        });
                    }
                    //设置缓存
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_PAD_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                }else{
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_PAD_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            }else{
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_FLOOR_PAD_CACHE + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME,  new ArrayList<>());
            }
        }
        return list == null ? new ArrayList<>() : list;
    }


    /**
     * <desc>
     *      获取用户云对讲设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否 3云对讲推送业务获取云对讲设备
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppCloudIntercomsVO> getCloudIntercoms( String userId,String projectId,Integer updateCache) throws Exception {
        List<AppCloudIntercomsVO> list= (List<AppCloudIntercomsVO>) redisService.decodeObject(
                RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId, new TypeReference<List<AppCloudIntercomsVO>>(){});
        if(updateCache == 3 || (updateCache == 0 && list == null) || (updateCache==1)) {
            //获取sip账号信息
            SipClusterPO sip=iAppDeviceDao.getSipInfoByProjectId(projectId);
            List<Map<String,Object>> cloudAuth = iAppDeviceDao.getCloudIntercomsAuth(userId, projectId);
            AppEntranceOrCloudIntercomAuthVO cloudVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(),cloudAuth);
            //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
            if (cloudVO != null) {
                String[] cloudIntercoms = cloudVO.getDeviceIds().toArray(new String[cloudVO.getDeviceIds().size()]);
                if (cloudIntercoms !=null && cloudIntercoms.length > 0) {
                    list = iAppDeviceDao.getCloudIntercoms(userId, projectId, cloudIntercoms);
                    //获取该用户所有云对讲设备所属楼栋用户房间号
                    List<Map<String,Object>> rooms=iAppDeviceDao.getCloudUserRooms(cloudIntercoms, projectId, userId);
                    if (null != list && !list.isEmpty()){
                        list.forEach(cloud->{
                            //设置sip账号
                            if(StringUtils.isNotBlank(cloud.getSipAccount())&&sip!=null&&StringUtils.isNotBlank(sip.getSipAddress())
                                    &&sip.getSipPort()!=null){
//                                cloud.setSipAccount(cloud.getSipAccount()+"@"+sip.getSipAddress()+":"+sip.getSipPort());
                                cloud.setSipAccount(cloud.getSipAccount());
                            }
                            StringBuilder roomId=new StringBuilder();
                            StringBuilder roomNum=new StringBuilder();
                            rooms.forEach(room->{
                                if(room.get("deviceUnique").toString().equals(cloud.getDeviceUnique())) {
                                    roomId.append(room.get("roomId") + ",");
                                    if (room.get("smartType").toString().equals("31")) {
                                        roomNum.append(room.get("roomNum") + ",");
                                    }
                                }
                            });
                            if(roomId.length() > 0) {
                                cloud.setRoomIds(roomId.substring(0,roomId.length()-1));
                                //如果是门口机加上房间编号
                                if(roomNum.length() > 0) {
                                    cloud.setRoomNum(roomNum.substring(0, roomNum.length() - 1));
                                }
                            }
                            try {
                                cloud.setValiTime(DateUtil.formatStringToDate(cloudVO.getValiTime(),DateUtil.YYMMDDHHMMSS).getTime()+"");
                            } catch (ParseException e) {
                                LOG.error("【云对讲有效时间转换失败】");
                            }
                        });
                        if(updateCache!=3) {
                            //设置缓存
                            redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                                    RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                        }
                    }else{
                        if(updateCache!=3) {
                            //设置缓存
                            redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                                    RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                        }
                    }
                }else{
                    if(updateCache!=3) {
                        //设置缓存
                        redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                                RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                    }
                }
            }else{
                if(updateCache!=3) {
                    //设置缓存
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取用户云对讲设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否 3云对讲推送业务获取云对讲设备
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppCloudIntercomsVO> getTempCloudIntercoms( String userId,String projectId,Integer updateCache) throws Exception {
        List<AppCloudIntercomsVO> list= (List<AppCloudIntercomsVO>) redisService.decodeObject(
                RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId, new TypeReference<List<AppCloudIntercomsVO>>(){});
        if(updateCache == 3 || (updateCache == 0 && list == null) || (updateCache==1)) {
            //获取sip账号信息
            SipClusterPO sip=iAppDeviceDao.getSipInfoByProjectId(projectId);
            List<Map<String,Object>> cloudAuth = iAppDeviceDao.getTempCloudIntercomsAuth(userId, projectId);
            AppEntranceOrCloudIntercomAuthVO cloudVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(),cloudAuth);
            //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
            if (cloudVO != null) {
                String[] cloudIntercoms = cloudVO.getDeviceIds().toArray(new String[cloudVO.getDeviceIds().size()]);
                if (cloudIntercoms !=null && cloudIntercoms.length > 0) {
                    list = iAppDeviceDao.getCloudIntercoms(userId, projectId, cloudIntercoms);
                    //获取该用户所有云对讲设备所属楼栋用户房间号
                    List<Map<String,Object>> rooms=iAppDeviceDao.getCloudUserRooms(cloudIntercoms, projectId, userId);
                    if (null != list && !list.isEmpty()){
                        list.forEach(cloud->{
                            //设置sip账号
                            if(StringUtils.isNotBlank(cloud.getSipAccount())&&sip!=null&&StringUtils.isNotBlank(sip.getSipAddress())
                                    &&sip.getSipPort()!=null){
//                                cloud.setSipAccount(cloud.getSipAccount()+"@"+sip.getSipAddress()+":"+sip.getSipPort());
                                cloud.setSipAccount(cloud.getSipAccount());
                            }
                            StringBuilder roomId=new StringBuilder();
                            StringBuilder roomNum=new StringBuilder();
                            rooms.forEach(room->{
                                if(room.get("deviceUnique").toString().equals(cloud.getDeviceUnique())) {
                                    roomId.append(room.get("roomId") + ",");
                                    if (room.get("smartType").toString().equals("31")) {
                                        roomNum.append(room.get("roomNum") + ",");
                                    }
                                }
                            });
                            if(roomId.length() > 0) {
                                cloud.setRoomIds(roomId.substring(0,roomId.length()-1));
                                //如果是门口机加上房间编号
                                if(roomNum.length() > 0) {
                                    cloud.setRoomNum(roomNum.substring(0, roomNum.length() - 1));
                                }
                            }
                            try {
                                cloud.setValiTime(DateUtil.formatStringToDate(cloudVO.getValiTime(),DateUtil.YYMMDDHHMMSS).getTime()+"");
                            } catch (ParseException e) {
                                LOG.error("【云对讲有效时间转换失败】");
                            }
                        });
                        if(updateCache!=3) {
                            //设置缓存
                            redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                                    RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                        }
                    }else{
                        if(updateCache!=3) {
                            //设置缓存
                            redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                                    RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                        }
                    }
                }else{
                    if(updateCache!=3) {
                        //设置缓存
                        redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                                RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                    }
                }
            }else{
                if(updateCache!=3) {
                    //设置缓存
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_CLOUD_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            }
        }
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      根据用户查询云对讲设备房间
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param deviceUnique 设备编号
     * @return
     * @author Qiang.S
     * @createDate 2019/06/10
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getCloudIntercomRoomInfo( String userId,String projectId,String deviceUnique) throws Exception {
        //获取该用户所有云对讲设备所属楼栋用户房间号
        List<Map<String,Object>> rooms = iAppDeviceDao.getCloudUserRooms(deviceUnique.split(","), projectId, userId);
        StringBuilder roomNum=new StringBuilder();
        rooms.forEach(room->{
            if (room.get("smartType").toString().equals("31")) {
                roomNum.append(room.get("roomNum") + "-");
            }
        });
        if  (roomNum.length() == 0) {
            roomNum.append("0");
        }
        return roomNum.toString();
    }


    /**
     * <desc>
     *      更新设备排序值
     * <desc/>
     *
     * @param userId 用户id
     * @param projectId 项目id
     * @param orderDTOS 设备排序值列表
     * @return
     * @author Chunjian.G
     * @createDate 2017-11-08
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer updateDeviceOrders(String userId, String projectId, List<AppDeviceOrderDTO> orderDTOS) throws Exception {

        String elevatorOrders = null, doorOrders = null, cloudIntercomOrders = null;
        for (AppDeviceOrderDTO order : orderDTOS){
            String devUnique = order.getDeviceUnique();
            switch (PropertyEquipTypeEnum.getByEquipType(StringHandlerUtil.getDeviceTypeByDeviceUnique(devUnique))){
                case ELEVATOR:
                    elevatorOrders = null == elevatorOrders ? "" : elevatorOrders
                            + StringHandlerUtil.getDeviceIdByDeviceUnique(devUnique)
                            + StringHandlerUtil.formatStrLen(order.getPosition(),"0",4,false,true)
                            + ",";
                    break;
                case ENTRANCE:
                    doorOrders = null == doorOrders ? "" : doorOrders
                            + StringHandlerUtil.getDeviceIdByDeviceUnique(devUnique)
                            + StringHandlerUtil.formatStrLen(order.getPosition(),"0",4,false,true)
                            + ",";
                    break;
                case CLOUD_INTERCOM:
                    cloudIntercomOrders = null == cloudIntercomOrders ? "" : cloudIntercomOrders
                            + StringHandlerUtil.getDeviceIdByDeviceUnique(devUnique)
                            + StringHandlerUtil.formatStrLen(order.getPosition(),"0",4,false,true)
                            + ",";
                    break;
                default:
                    break;
            }
        }
        Integer result = null;
        if (null != elevatorOrders){
            result = iAppDeviceDao.updateDeviceOrders(userId, projectId,
                    PropertyEquipTypeEnum.ELEVATOR.getType(), elevatorOrders);
        }
        if (null != doorOrders){
            result = iAppDeviceDao.updateDeviceOrders(userId, projectId,
                    PropertyEquipTypeEnum.ENTRANCE.getType(), doorOrders);
        }
        if (null != cloudIntercomOrders){
            result = iAppDeviceDao.updateDeviceOrders(userId, projectId,
                    PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(), cloudIntercomOrders);
        }
        return result;
    }

    /**
     * <desc>
     *      更新用户设备列表缓存信息
     * </desc>
     *
     * @param projectId 项目id
     * @param userId 用户id
     * @author Jiaqi.X
     * @createDate 2017/11/13
     */
    @Override
    public void updateUserDevicesInfoCache(String projectId, String userId,String dataJs,String userIdList) throws Exception {
        cachedThreadPool.execute(()->{
            try {
                Thread.sleep(2000);
                if (StringUtils.isNotBlank(userId)) {
                    this.getDoorDevices(userId, projectId, 1);
                    this.getCloudIntercoms(userId, projectId, 1);
                    this.getFloorDevices(userId, projectId, 1);
                }else if(StringUtils.isNotBlank(userIdList)){
                    //更新一卡通用户权限
                    List<Map<String,Object>> userList = JsonUtil.decode(userIdList, new TypeReference<List<Map<String, Object>>>(){});
                    for(Map<String,Object> user : userList){
                        this.getDoorDevices(user.get("userId").toString(), user.get("projectId").toString(), 1);
                        this.getCloudIntercoms(user.get("userId").toString(), user.get("projectId").toString(), 1);
                        this.getFloorDevices(user.get("userId").toString(), user.get("projectId").toString(), 1);
                    }
                }else{
                    //批量更新项目下的用户设备权限 根据项目id查询当前项目下的有效用户
                    List<String> userIds = iAppDeviceDao.getValidProjectUserId(projectId);
                    if (userIds != null && !userIds.isEmpty()) {
                        for (String user : userIds) {
                            //删除用户设备列表缓存0
                            this.getDoorDevices(user, projectId, 1);
                            this.getCloudIntercoms(user, projectId, 1);
                            this.getFloorDevices(user, projectId, 1);
                        }
                    }
                }
                if(dataJs!=null) {
                    Thread.sleep(2000);
                    Map<String,Object> map = new HashMap<>();
                    map.put("data",dataJs);
                    //极光推送
                    messageSender.send(RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_QUEUE,
                            JsonUtil.toJSON(map), RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_EXCHANGE,
                            RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_KEY);
                }
            }catch (Exception e){
                throw new DataAccessException("【更新APP用户缓存失败】",e);
            }
        });
    }

    /**
     * <desc>
     *      设置app用户二维码信息
     * </desc>
     *
     * @param userId 用户id
     * @param projectId 项目id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/15
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void  setUserQrCode(String userId,String projectId,String roomId) throws Exception {
        //处理没有有效批次号的设备，随同项目最近批次号过期而过期的标识
        boolean mark = false;
        //需要排除的旧批次号集合
        List<String> oldBatchNumberArr = new ArrayList<>();
        //查询出需排除的旧批次集合
        List<String> oldBatchNumberList = iAppDeviceDao.getOldBatchNumberByProjectId(projectId);
        for(String oldBatchNumbers : oldBatchNumberList){
            for(String oldBatchNumber : oldBatchNumbers.split(",")){
                oldBatchNumberArr.add(oldBatchNumber);
            }
        }
        //获取项目下最近批次号过期时间
        String endTimeByProjectId = iAppDeviceDao.getBatchNumberEndTimeByProjectId(projectId,oldBatchNumberArr.size()>0?oldBatchNumberArr:null);
        if(StringUtils.isNotEmpty(endTimeByProjectId)){
            Date endDate = DateUtil.fomatLongDate2(endTimeByProjectId);
            Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
            Integer endDays = DateUtil.differentDays(nowDate, endDate);
            if (endDays < -3) {
                mark = true;
            }
        }
        PropertyQrcodeValidVO valid = null;
        //获取项目二维码配置信息
        if(StringUtils.isNotBlank(roomId)) {
            valid=iAppDeviceDao.getPropertyQrocdeVliadInfo(roomId);
            if(valid != null && valid.getProjectChargeMode() ==2){
                //新二维码格式
                String qrcodeContent = this.setNewUserQrCode(userId,projectId,roomId,mark);

                //是否保存生成二维码记录标记
                boolean qrcodeFlag = true;
                if (valid.getRoomChargeMode() !=null){
                    //有效次数为0，app不会生成二维码
                    if (valid.getRoomChargeMode() == 1 && valid.getUsableCount() <=0){
                        qrcodeFlag = false;
                    }
                    //二维码过期，app不会生成二维码
                    if (valid.getRoomChargeMode() == 2){
                        Date now = DateUtil.formatStringToDate(DateUtil.fomatDate(new Date(), DateUtil.YMDSQL), DateUtil.YMDSQL);
                        if(StringUtils.isNotBlank(valid.getEndTime())){
                            Date roomDate = DateUtil.formatStringToDate(valid.getEndTime(),DateUtil.YMDSQL);
                            if(roomDate.getTime() < now.getTime()){
                                qrcodeFlag = false;
                            }
                        }
                    }
                }
                //保存开启了共享电梯项目生成的二维码记录
                if (StringUtils.isNotBlank(qrcodeContent) && qrcodeFlag){
                    SharedElevatorQrCodeRecordPO recordPO = new SharedElevatorQrCodeRecordPO();
                    recordPO.setCodeId(LogicIdUtil.bussinessId());
                    recordPO.setUserId(userId);
                    recordPO.setProjectId(projectId);
                    recordPO.setRoomId(roomId);
                    recordPO.setQrCodeContent(qrcodeContent);
                    recordPO.setRoomChargeMode(valid.getRoomChargeMode());
                    recordPO.setUsableCount(valid.getUsableCount());
                    recordPO.setEndTime(valid.getEndTime());
                    recordPO.setStatus(DataStatusEnum.NORMAL.getType());
                    recordPO.setCreateTime(new Date());
                    iAppDeviceDao.save(SqlUtil.durableData(recordPO,PlatformConstants.TABLE_SAVE));
                }
                return;
            }
        }
        String commonFloor = iAppDeviceDao.getCommonFloorByUserIdAndProjectId(userId,projectId);
        //获取项目下有权限的所有电梯设备信息
        List<AppFloorDevicesVO> floors = this.getFloorDevices(userId,projectId,0);
        //电梯设备unique 多个,号分隔
        StringBuilder floorUniques=new StringBuilder();
        for (int i = floors.size()-1 ; i>=0; i--) {
            if (StringUtils.isNotEmpty(floors.get(i).getBatchNumber())) {
                String endTime = iAppDeviceDao.getBatchNumberEndTime(floors.get(i).getBatchNumber());
                if(StringUtils.isNotEmpty(endTime)){
                    Date endDate = DateUtil.fomatLongDate2(endTime);
                    Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                    Integer endDays = DateUtil.differentDays(nowDate,endDate);
                    if(endDays<-3){
                        floors.remove(i);
                        continue;
                    }
                }else{
                    if(mark){
                        floors.remove(i);
                        continue;
                    }
                }
            }else{
                if(mark){
                    floors.remove(i);
                    continue;
                }
            }
            floorUniques.append(floors.get(i).getDeviceUnique() + ",");
        }
        //获取项目下有权限的所有门禁设备信息
        List<AppDoorDevicesVO> doors=this.getDoorDevicesByTemp(userId, projectId,0);
        //获取项目下有权限的云对讲设备信息
        List<AppCloudIntercomsVO> clouds=this.getCloudIntercoms(userId,projectId,0);
        //set用于去重
        Set<String> deviceSet=new HashSet<>();
        //门禁设备unique 多个,号分隔
        StringBuilder entrances=new StringBuilder();
        if(doors!=null && !doors.isEmpty()) {
            for (int i = doors.size()-1 ; i>=0; i--) {
                if (StringUtils.isNotEmpty(doors.get(i).getBatchNumber())) {
                    String endTime = iAppDeviceDao.getBatchNumberEndTime(doors.get(i).getBatchNumber());
                    if(StringUtils.isNotEmpty(endTime)){
                        Date endDate = DateUtil.fomatLongDate2(endTime);
                        Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                        Integer endDays = DateUtil.differentDays(nowDate, endDate);
                        if (endDays < -3) {
                            doors.remove(i);
                            continue;
                        }
                    }else{
                        if(mark){
                            doors.remove(i);
                            continue;
                        }
                    }
                }else{
                    if(mark){
                        doors.remove(i);
                        continue;
                    }
                }
                deviceSet.add(doors.get(i).getDeviceUnique().substring(doors.get(i).getDeviceUnique().length() - 4, doors.get(i).getDeviceUnique().length()));
                entrances.append(doors.get(i).getDeviceUnique().substring(doors.get(i).getDeviceUnique().length() - 4, doors.get(i).getDeviceUnique().length()) + ",");
            }
        }
        //云对讲设备 unique 多个，号分隔
        if(clouds != null && !clouds.isEmpty()){
            for (int i = clouds.size()-1 ; i>=0; i--) {
                if (deviceSet.add(clouds.get(i).getDeviceUnique().substring(clouds.get(i).getDeviceUnique().length() - 4, clouds.get(i).getDeviceUnique().length()))) {
                    if (StringUtils.isNotEmpty(clouds.get(i).getBatchNumber())) {
                        String endTime = iAppDeviceDao.getBatchNumberEndTime(clouds.get(i).getBatchNumber());
                        if(StringUtils.isNotEmpty(endTime)){
                            Date endDate = DateUtil.fomatLongDate2(endTime);
                            Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                            Integer endDays = DateUtil.differentDays(nowDate, endDate);
                            if (endDays < -3) {
                                clouds.remove(i);
                                continue;
                            }
                        }else{
                            if(mark){
                                clouds.remove(i);
                                continue;
                            }
                        }
                    }else{
                        if(mark){
                            clouds.remove(i);
                            continue;
                        }
                    }
                    entrances.append(clouds.get(i).getDeviceUnique().substring(clouds.get(i).getDeviceUnique().length() - 4, clouds.get(i).getDeviceUnique().length()) + ",");
                }
            }
        }
        //开始拼接二维码
        StringBuilder qrcode=new StringBuilder("");
        StringBuilder header = new StringBuilder("");
        //协议版本 1Byte, Hex码
        header.append(AppQrcodeProtocolVersionEnum.THIRD.getType());
        //用户类型 1Byte，Hex码。 暂定0x11表示物业管理员；0x12表示业主；0x13表示访客
        header.append(AppQrcodeUserTypeEnum.OWNER.getType());
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, 10);
        //用户UID 目前生成规则为用户手机号 不足6btye末尾补0
        String uid;
        //查询用户类型
        QrcodeUserInfoVO qrcodeUserInfo= iAppDeviceDao.getUserType(userId,projectId);
        //用户uid
        if(StringUtils.isNotBlank(qrcodeUserInfo.getUid())){
            uid = StringHandlerUtil.autlSupply(12,qrcodeUserInfo.getUid(),"0");
            qrcode.append(uid);
        }else{
            if(qrcodeUserInfo.getLastUid()!=null){
                uid = StringHandlerUtil.autlSupply(12,(qrcodeUserInfo.getLastUid()+1)+"","0");
                qrcode.append(uid);
            }else{
                uid = StringHandlerUtil.autlSupply(12,"1","0");
                qrcode.append(uid);
            }
            //保存uid
            iAppDeviceDao.updateUid(userId, projectId, uid.substring(uid.length()-8,uid.length()));
        }
        //qrcode.append(random.substring(random.length() - 12, random.length()));
        //生成日期 格式 yyMMddHHmm
        qrcode.append(DateUtil.fomatDate(DateUtil.reduceCurrentTime(new Date(),10*60*1000), DateUtil.YYMMDDHHMM));
        //新用户类型
//        String cacheKey=RedisConstant.REDIS_APP_OWNER_QRCODE_SERIAL_NUMBER_CACHE+userId+ DateUtil.fomatDate(new Date(), DateUtil.YYMMDD);
//        Integer serialNumber=(Integer)redisService.getObject(cacheKey, Integer.class);
//        if(serialNumber!=null){
//            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
//        }else{
//            serialNumber=1;
//            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
//        }
//        redisService.set(cacheKey, RedisConstant.REDIS_APP_OWNER_QRCODE_SERIAL_NUMBER_CACHE_TIME, Integer.valueOf(serialNumber)+1);
        //“M”表示用户类型标识符，用户类型固定1Byte，16进制表示。目前具体有以下类型：0x31授权二维码，0x32管理员用户，0x33表示业主或普通用户，0x34表示访客；0x35表示VIP用户、0x36表示残障用户；
        String[] types = StringHandlerUtil.splitString(qrcodeUserInfo.getUserLable());
        String type=new String();
        for(String t:types){
            if(StringUtils.isBlank(type)){
                type = t;
            }else if(t.equals("36")){
                type = t;
            }else if(t.equals("35") && type.equals(type)){
                type =t;
            }
        }
        if(StringUtils.isBlank(type)) {
            qrcode.append("33");
        }else if(type.equals("1")){
            //VIP
            qrcode.append("35");
        }else if(type.equals("2")){
            //障碍人士
            qrcode.append("36");
        }
        //有效时间 hex 码
        qrcode.append("0D");
        //有效次数 hex码
        qrcode.append("01");
        //用户拥有权限的电梯设备楼栋信息及房屋楼栋信息的交集 既最终用户所拥有的有权限的电梯设备楼栋信息
        Map<String, List<AppFloorDevicesVO>> userAuthFloorRoomsBuildAndUnit = new HashMap<>();
        //电梯楼层权限筛选
        Set<String> floorSet = new HashSet<>();
        if(StringUtils.isNotBlank(commonFloor)){
            Map<String,Object> commanFloors = JsonUtil.toObject(commonFloor,HashMap.class);
            for(String deviceUnique : commanFloors.keySet()){
                Optional<AppFloorDevicesVO> optional = floors.stream().filter(floor -> floor.getDeviceUnique().equals(deviceUnique)
                        && StringHandlerUtil.splitStringToArray(floor.getLiveFloor()).stream().filter
                        (f -> f.equals(commanFloors.get(deviceUnique).toString())).findFirst().isPresent()).findFirst();
                if(optional.isPresent()){
                    optional.get().setCommonChoiceFloor(commanFloors.get(deviceUnique).toString());
                }
            }
        }
        //组装用户电梯机号 按电梯楼层权限分组
        for(AppFloorDevicesVO floorVO : floors){
            List<AppFloorDevicesVO> list;
            if(floorSet.add(floorVO.getLiveFloor()+"c"+
                    (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""))){
                list=new ArrayList<>();
            }else{
                list=userAuthFloorRoomsBuildAndUnit.get(floorVO.getLiveFloor()+"c"+
                        (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""));
            }
            list.add(floorVO);
            userAuthFloorRoomsBuildAndUnit.put(floorVO.getLiveFloor()+"c"+
                    (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""),list);
        }
        //判断是否有电梯设备的权限
//        if(StringUtils.isNotBlank(floorUniques.toString())) {
//            //筛选出用户有权限的电梯设备楼栋信息
//            userAuthFloorRoomsBuildAndUnit = iAppDeviceDao.
//                    getUserAuthFloorRoomBuildAndUnit(StringHandlerUtil.splitString(floorUniques.toString()));
//        }

        String identifier;
        //电梯门禁标识 HEX码 如有电梯和门禁权限时为0x03；只有电梯而无门禁权限时为0x01；只有门禁权限时为0x02
        if(!userAuthFloorRoomsBuildAndUnit.isEmpty() && StringUtils.isNotBlank(entrances.toString())){
            qrcode.append("03");
            identifier="03";
        }else if(!userAuthFloorRoomsBuildAndUnit.isEmpty()){
            qrcode.append("01");
            identifier="01";
        }else if(StringUtils.isNotBlank(entrances.toString())){
            qrcode.append("02");
            identifier="02";
        }else{
            qrcode.append("00");
            identifier=("00");
        }
        if(!identifier.equals("00")) {
            //门禁
            if(!identifier.equals("01")) {
                //设置二维码的门禁数量
                String[] entranceDeviceUniques = StringHandlerUtil.splitString(entrances.toString());
                qrcode.append(entranceDeviceUniques.length < 255 ? StringHandlerUtil.autlSupply(2, Integer.toHexString(entranceDeviceUniques.length).toUpperCase(), "0") : "FF");
                if (entranceDeviceUniques.length > 0 && entranceDeviceUniques.length < 255) {
                    //设置二维码的门禁权限 HEX码
                    qrcode.append(StringHandlerUtil.assembleDeviceNum(entranceDeviceUniques));
                }
            }
            //电梯
            if(!identifier.equals("02")) {
                //有权限的电梯楼栋单元数量 最多8个单元 超过8个单元按拥有所有电梯权限处理
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(userAuthFloorRoomsBuildAndUnit.size()).toUpperCase(), "0"));
                //设置二维码的电梯权限
                for (Map.Entry<String, List<AppFloorDevicesVO>> floorMap : userAuthFloorRoomsBuildAndUnit.entrySet()) {
                    List<AppFloorDevicesVO> floorVos=floorMap.getValue();
                    //设置二维码当前楼栋有权限的电梯数量 HEX码
                    qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(floorVos.size()).toUpperCase(), "0"));
                    //当前楼栋的电梯机号
                    StringBuilder currentFloorIds = new StringBuilder();
                    floorVos.forEach(cf -> {
                        currentFloorIds.append(cf.getDeviceUnique().substring(cf.getDeviceUnique().length()-4,cf.getDeviceUnique().length()) + ",");
                    });
                    //设置二维码当前楼栋有权限的电梯机号
                    qrcode.append(StringHandlerUtil.assembleDeviceNum(StringHandlerUtil.splitString(currentFloorIds.toString())));
                    //设置有权限的楼层数量 HEX码
                    String fl = floorMap.getKey();
                    String[] floorNo = StringHandlerUtil.splitString(fl.substring(0,fl.indexOf("c")));
                    String chCommonFloor = fl.substring(fl.indexOf("c")+1,fl.length());
                    if (floorNo.length == 112) {
                        qrcode.append("FF");
                    } else {
                        qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(floorNo.length).toUpperCase(), "0"));
                        //设置有权限的楼层号
                        qrcode.append(StringHandlerUtil.assembleDeviceNum(floorNo));
                    }
                    //设置直达楼层
                    if(StringUtils.isNotBlank(chCommonFloor) && !chCommonFloor.equals("c") &&
                            chCommonFloor.length() > chCommonFloor.indexOf("c")&&!chCommonFloor.equals("null")){
                        qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(chCommonFloor)).toUpperCase(), "0"));
                    }else{
                        for(int i=0; i < floorVos.size() ; i++ ){
                            if(StringUtils.isNotBlank(floorVos.get(i).getLiveChoiceFloor())){
                                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floorVos.get(i).getCommonChoiceFloor())).toUpperCase(), "0"));
                                break;
                            }
                            if(i == floorVos.size()-1){
                                //没有直达楼层设置00
                                if(projectId.equals("88888888")&&qrcodeRunEnvironment.equals("test")) {
                                    //201环境下项目88888888设置默认楼层为7
                                    qrcode.append("07");
                                }else{
                                    qrcode.append("00");
                                }
                            }
                        }
                    }
                }
            }
        }
        String value=qrcode.substring(12,28);
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(projectId);
        qrcode = new StringBuilder(header.toString()+qrcode.toString());
        qrcode=qrcode.append(DesEncryptUtil.ownerAndVisitorMacEncrypt(value, projectKey, qrcode.toString()));
        //获取项目二维码长度
        Integer codeLength = iAppDeviceDao.getCodeLength(projectId);
        if((valid == null || valid.getProjectChargeMode() == 1) && codeLength != null && qrcode.length() >= codeLength*2){
            roomId = null;
            //新二维码格式
            this.setNewUserQrCode(userId,projectId,roomId,mark);
            return;
        }
        //保存用户二维码
        iAppDeviceDao.updateUserQrCode(userId,projectId,qrcode.toString(),DateUtil.fomatDate1(DateUtil.addCurrentTime(7)),null, System.currentTimeMillis() + 120 * 60 * 1000);
    }

    /**
     * <desc>
     *      获取用户无接触二维码
     * </desc>
     *
     * @param userId 用户编号
     * @param deviceUnique 设备编号
     * @param logicalFloor 楼层
     * @return
     * @author Qiang.S
     * @createDate 2020/02/28
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String  getNoTouchQRCode(String userId,String deviceUnique,String logicalFloor) throws Exception {
        //开始拼接二维码
        StringBuilder heard=new StringBuilder("ITL:{L:");
        StringBuilder content = new StringBuilder();
        //协议版本 1Byte, Hex码
        content.append("V:"+AppQrcodeProtocolVersionEnum.NEW.getType()+",");
        //查询用户类型
        QrcodeUserInfoVO qrcodeUserInfo= iAppDeviceDao.getUserType(userId,deviceUnique.substring(0, 8));
        //用户uid
        if(StringUtils.isNotBlank(qrcodeUserInfo.getUid())){
            content.append("U:"+qrcodeUserInfo.getUid()+",");
        }else{
            String uid;
            if(qrcodeUserInfo.getLastUid()!=null){
                uid = StringHandlerUtil.autlSupply(8,(qrcodeUserInfo.getLastUid()+1)+"","0");
                content.append("U:"+uid+",");
            }else{
                uid = StringHandlerUtil.autlSupply(8,"1","0");
                content.append("U:"+uid+",");
            }
            //保存uid
            iAppDeviceDao.updateUid(userId, deviceUnique.substring(0, 8), uid);
        }
        //“M”表示用户类型标识符，用户类型固定1Byte，16进制表示。目前具体有以下类型：0x31授权二维码，0x32管理员用户，0x33表示业主或普通用户，0x34表示访客；0x35表示VIP用户、0x36表示残障用户；
        String[] types = StringHandlerUtil.splitString(qrcodeUserInfo.getUserLable());
        String type=new String();
        for(String t:types){
            if(StringUtils.isBlank(type)){
                type = t;
            }else if(t.equals("36")){
                type = t;
            }else if(t.equals("35") && type.equals(type)){
                type =t;
            }
        }
        if(StringUtils.isBlank(type)) {
            content.append("M:33,");
        }else if(type.equals("1")){
            //VIP
            content.append("M:35,");
        }else if(type.equals("2")){
            //障碍人士
            content.append("M:36,");
        }
        //房间编号
        Integer roomNo = 0;
        content.append("H:"+StringHandlerUtil.autlSupply(2,Integer.toHexString(roomNo),"0")+",");
        //批次号批次或流水号：“B:xxxx”其中“B”表示标识，批次值占用2个字节，用16进制表示0x0000—0xFFFF。
        content.append("I:0001,".toUpperCase());
        String startTime = DateUtil.fomatDate(DateUtil.reduceCurrentTime(new Date(),10*60*1000), DateUtil.YYMMDDHHMM);

        //启用时间
        content.append("T:" +startTime+ ",");
        //有效时间 hex 码
        content.append("P:0082,");
        //有效次数 hex码
        content.append("S:0000,");
        String validCount = "00";
        String value = startTime + "0082" + validCount;

        //设置机号权限N1：xxx
        String n1 = StringHandlerUtil.assembleQrcodeDeviceNum(StringHandlerUtil.splitString(deviceUnique.substring(deviceUnique.length()-4,deviceUnique.length())));
        content.append("Q:{N1:" + n1 + ",");

        String[] floorsStr = new String[]{logicalFloor};
        String x1 = StringHandlerUtil.assembleQrcodeDeviceNum(floorsStr);
        content.append("X1:" + x1 + ",");
        content.append("Y:" + x1);
        content.append("},");
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(deviceUnique.substring(0, 8));
        String mac="K:"+DesEncryptUtil.newOwnerAndVisitorMacEncrypt(value, projectKey, content.toString());
        String qrcode = heard.toString()+ StringHandlerUtil.autlSupply(4,Integer.toHexString((content + mac).length()).toUpperCase(),"0") +","+content+mac+"}";
        return qrcode;
    }

    /**
     * <desc>
     *      生成管理员二维码
     * </desc>
     *
     * @param userId
     * @param projectId
     */
    private void setManageQrcode(String userId,String projectId) throws NoSuchProviderException {
        //开始拼接二维码
        StringBuilder heard=new StringBuilder("ITL:{L:");
        StringBuilder content = new StringBuilder();
        //协议版本 1Byte, Hex码
        content.append("V:"+AppQrcodeProtocolVersionEnum.NEW.getType()+",");
        //查询用户类型
        QrcodeUserInfoVO qrcodeUserInfo= iAppDeviceDao.getUserType(userId,projectId);
        //用户uid
        if(StringUtils.isNotBlank(qrcodeUserInfo.getUid())){
            content.append("U:"+qrcodeUserInfo.getUid()+",");
        }else{
            String uid;
            if(qrcodeUserInfo.getLastUid()!=null){
                uid = StringHandlerUtil.autlSupply(8,(qrcodeUserInfo.getLastUid()+1)+"","0");
                content.append("U:"+uid+",");
            }else{
                uid = StringHandlerUtil.autlSupply(8,"1","0");
                content.append("U:"+uid+",");
            }
            //保存uid
            iAppDeviceDao.updateUid(userId, projectId, uid);
        }
        //“M”表示用户类型标识符，用户类型固定1Byte，16进制表示。目前具体有以下类型：0x31授权二维码，0x32管理员用户，0x33表示业主或普通用户，0x34表示访客；0x35表示VIP用户、0x36表示残障用户；
        content.append("M:32,");
        //房间编号
        content.append("H:00,");
        //批次号批次或流水号：“B:xxxx”其中“B”表示标识，批次值占用2个字节，用16进制表示0x0000—0xFFFF。
        content.append("I:0001,");
        String startTime = DateUtil.fomatDate(DateUtil.reduceCurrentTime(new Date(),10*60*1000), DateUtil.YYMMDDHHMM);
        //启用时间
        content.append("T:" +startTime+ ",");
        //有效时间 hex 码
        content.append("P:0288,");
        String validCount;
        //有效次数 hex码
        content.append("S:0000,");
        validCount = "00";
        if(validCount.length()>2){
            validCount=validCount.substring(2,4);
        }
        String value =startTime+"0288"+validCount;
        content.append("G:{N3:0},Q:{N3:0,X3:0,Y:0},");
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(projectId);
        String mac="K:"+DesEncryptUtil.newOwnerAndVisitorMacEncrypt(value, projectKey, content.toString());
        String qrcode = heard.toString()+ StringHandlerUtil.autlSupply(4,Integer.toHexString((content + mac).length()).toUpperCase(),"0") +","+content+mac+"}";
        //保存用户二维码
        iAppDeviceDao.updateUserQrCode(userId,projectId,qrcode.toString(),DateUtil.fomatDate1(DateUtil.addCurrentTime(7)),null, System.currentTimeMillis() + 120 * 60 * 1000);
    }

    /**
     * <desc>
     *      设置app用户二维码信息
     * </desc>
     *
     * @param userId 用户id
     * @param projectId 项目id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/15
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String setNewUserQrCode(String userId,String projectId,String roomId,boolean mark) throws Exception {
        RoomInfoPO room = null;
        PropertyQrcodeValidVO valid = null;
        if(StringUtils.isNotBlank(roomId)){
            room=iAppVisitorPassCodeRecordDao.getRoomBuildAndUnitInfo(roomId, projectId, userId);
            valid=iAppDeviceDao.getPropertyQrocdeVliadInfo(roomId);
        }
        String commonFloor = iAppDeviceDao.getCommonFloorByUserIdAndProjectId(userId,projectId);
        //获取项目下有权限的所有电梯设备信息
        List<AppFloorDevicesVO> floors=this.getFloorDevices(userId, projectId, 0);
        List<AppFloorDevicesVO> tempFloors;
        if(StringUtils.isBlank(roomId)){
            tempFloors = this.getSmartCardFloorDevices(userId, projectId, 0);
        }else{
            tempFloors = this.getTempFloorDevices(userId,projectId,0);
        }
        if(StringUtils.isNotBlank(roomId)) {
            //过滤已有地址权限的临时权限
            List<AppFloorDevicesVO> addressList = this.getAddressFloorDevices(userId, projectId, 0);
            for(int j = tempFloors.size()-1;j >= 0; j--){
                AppFloorDevicesVO temp = tempFloors.get(j);
                Optional<AppFloorDevicesVO> address = addressList.stream().filter(a->a.getDeviceUnique().equals(temp.getDeviceUnique())).findFirst();
                if(address.isPresent()){
                    List<String> tempFloorsStr = new ArrayList<>(Arrays.asList(StringHandlerUtil.splitString(temp.getLiveFloor())));
                    List<String> addressFloors =new ArrayList<>(Arrays.asList(StringHandlerUtil.splitString(address.get().getLiveFloor())));
                    if(!tempFloorsStr.isEmpty() && !addressFloors.isEmpty()){
                        for(int i=tempFloorsStr.size() - 1 ; i >= 0 ; i--){
                            String f = tempFloorsStr.get(i);
                            if(addressFloors.stream().filter(addressFloor->addressFloor.equals(f)).findFirst().isPresent()){
                                tempFloorsStr.remove(i);
                            }
                        }
                        if(tempFloorsStr.isEmpty()){
                            tempFloors.remove(j);
                        }else{
                            temp.setLiveFloor(StringUtils.join(tempFloorsStr,","));
                        }
                    }
                }
            }
            for (int i = floors.size() - 1; i >= 0; i--) {
                AppFloorDevicesVO elevator = floors.get(i);
                if (iAppDeviceDao.checkElevatorInRoomAddress(elevator.getDeviceUnique(), room.getUnitId()) == 0 || !elevator.getLiftDoorType().equals(room.getLiftDoorType())) {
                    floors.remove(i);
                    continue;
                }
                if (StringUtils.isNotEmpty(floors.get(i).getBatchNumber())) {
                    String endTime = iAppDeviceDao.getBatchNumberEndTime(floors.get(i).getBatchNumber());
                    if(StringUtils.isNotEmpty(endTime)){
                        Date endDate = DateUtil.fomatLongDate2(endTime);
                        Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                        Integer endDays = DateUtil.differentDays(nowDate,endDate);
                        if(endDays<-3){
                            floors.remove(i);
                            continue;
                        }
                    }else{
                        if(mark){
                            floors.remove(i);
                            continue;
                        }
                    }
                }else{
                    if(mark){
                        floors.remove(i);
                        continue;
                    }
                }
                elevator.setLiveFloor( iAppDeviceDao.getNaturalFloorByRoomNum(room.getRoomNum().substring(0, 2), elevator.getDeviceUnique()));
            }
            for (AppFloorDevicesVO temp : tempFloors) {
                Optional<AppFloorDevicesVO> optional = floors.stream().filter(f -> f.getDeviceUnique().equals(temp.getDeviceUnique())).findFirst();
                if (optional.isPresent()) {
                    String[] fs = StringHandlerUtil.splitString(temp.getLiveFloor());
                    Set<String> fl = new HashSet<>();
                    for (String f : fs) {
                        fl.add(f);
                    }
                    fl.add(optional.get().getLiveFloor());
                    optional.get().setLiveFloor(StringUtils.join(fl, ","));
                } else {
                    if (StringUtils.isNotBlank(temp.getLiveFloor())) {
                        if (StringUtils.isNotEmpty(temp.getBatchNumber())) {
                            String endTime = iAppDeviceDao.getBatchNumberEndTime(temp.getBatchNumber());
                            if (StringUtils.isNotEmpty(endTime)) {
                                Date endDate = DateUtil.fomatLongDate2(endTime);
                                Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                                Integer endDays = DateUtil.differentDays(nowDate, endDate);
                                if (endDays < -3) {
                                    continue;
                                }
                            }else{
                                if(mark){
                                    continue;
                                }
                            }
                        }else{
                            if(mark){
                                continue;
                            }
                        }
                        floors.add(temp);
                    }
                }
            }
        }
        //获取项目下有权限的所有门禁设备信息
        List<AppDoorDevicesVO> doors=this.getDoorDevicesByTemp(userId, projectId, 0);
        //获取项目下有权限的云对讲设备信息
        List<AppCloudIntercomsVO> clouds=this.getCloudIntercoms(userId,projectId,0);
        //set用于去重
        Set<String> deviceSet=new HashSet<>();
        //门禁设备unique 多个,号分隔
        StringBuilder entrances=new StringBuilder();
        if(doors!=null && !doors.isEmpty()) {
            for (int i = doors.size()-1 ; i>=0; i--) {
                if (StringUtils.isNotEmpty(doors.get(i).getBatchNumber())) {
                    String endTime = iAppDeviceDao.getBatchNumberEndTime(doors.get(i).getBatchNumber());
                    if(StringUtils.isNotEmpty(endTime)){
                        Date endDate = DateUtil.fomatLongDate2(endTime);
                        Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                        Integer endDays = DateUtil.differentDays(nowDate, endDate);
                        if (endDays < -3) {
                            doors.remove(i);
                            continue;
                        }
                    }else{
                        if(mark){
                            doors.remove(i);
                            continue;
                        }
                    }
                }else{
                    if(mark){
                        doors.remove(i);
                        continue;
                    }
                }
                deviceSet.add(doors.get(i).getDeviceUnique().substring(doors.get(i).getDeviceUnique().length() - 4, doors.get(i).getDeviceUnique().length()));
                entrances.append(doors.get(i).getDeviceUnique().substring(doors.get(i).getDeviceUnique().length() - 4, doors.get(i).getDeviceUnique().length()) + ",");
            }
        }
        if(StringUtils.isNotBlank(roomId)) {
            if (entrances.length() > 0) {
                //筛选地址下的门禁
                StringBuilder addressEntrance = new StringBuilder();
                addressEntrance.append(iAppDeviceDao.getEntranceDeviceIdsForBridge(projectId,
                        room.getBuildId(), room.getUnitId(), StringHandlerUtil.splitString(entrances.toString())));
                if (addressEntrance.length() > 0 && !addressEntrance.toString().equals("null")) {
                    entrances = new StringBuilder();
                    entrances.append(addressEntrance + ",");
                }else{
                    entrances = new StringBuilder();
                }
            }
            //此处为了解决当房间下的用户有云对讲是和门禁相同机号的权限时，前提门禁是普通门禁或一卡通同步的权限时，会把相同机号云对讲的权限也给剔除掉的问题
            if(StringUtils.isNotBlank(entrances.toString())){
                String entrancesStr = entrances.toString();
                if(entrancesStr.endsWith(",")){
                    entrancesStr = entrancesStr.substring(0,entrancesStr.length()-1);
                }
                deviceSet = new HashSet<>(Arrays.asList(StringHandlerUtil.splitString(entrancesStr)));
            }
        }
        StringBuilder talks = new StringBuilder();
        //云对讲设备 unique 多个，号分隔
        if(clouds != null && !clouds.isEmpty()){
            for (int i = clouds.size()-1 ; i>=0; i--) {
                if (deviceSet.add(clouds.get(i).getDeviceUnique().substring(clouds.get(i).getDeviceUnique().length() - 4, clouds.get(i).getDeviceUnique().length()))) {
                    if (StringUtils.isNotEmpty(clouds.get(i).getBatchNumber())) {
                        String endTime = iAppDeviceDao.getBatchNumberEndTime(clouds.get(i).getBatchNumber());
                        if(StringUtils.isNotEmpty(endTime)){
                            Date endDate = DateUtil.fomatLongDate2(endTime);
                            Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                            Integer endDays = DateUtil.differentDays(nowDate, endDate);
                            if (endDays < -3) {
                                clouds.remove(i);
                                continue;
                            }
                        }else{
                            if(mark){
                                clouds.remove(i);
                                continue;
                            }
                        }
                    }else{
                        if(mark){
                            clouds.remove(i);
                            continue;
                        }
                    }
                    talks.append(clouds.get(i).getDeviceUnique().substring(clouds.get(i).getDeviceUnique().length() - 4, clouds.get(i).getDeviceUnique().length()) + ",");
                }
            }
        }
        if(StringUtils.isNotBlank(roomId)){
            //筛选地址下的云对讲
            if (talks.length() > 0) {
                //筛选地址下的门禁
                StringBuilder addressTalks = new StringBuilder();
                addressTalks.append(iAppDeviceDao.getTalkDeviceIdsForBridge(projectId,
                        room.getBuildId(), room.getUnitId(), StringHandlerUtil.splitString(talks.toString())));
                if (addressTalks.length() > 0 && !addressTalks.toString().equals("null")) {
                    talks = new StringBuilder();
                    talks.append(addressTalks + ",");
                }else{
                    talks = new StringBuilder();
                }
            }
        }
        entrances.append(talks.length() > 0 && !talks.equals("null") ? talks : "");
        if(StringUtils.isNotBlank(roomId)) {
            //获取临时权限
            List<AppDoorDevicesVO> tempDoors;
            if (StringUtils.isBlank(roomId)) {
                tempDoors = this.getSmartCardDoorDevices(userId, projectId, 1);
            } else {
                tempDoors = this.getTempDoorDevices(userId, projectId, 1);
            }

            for (int i = tempDoors.size()-1 ; i>=0; i--) {
                if (entrances.indexOf(tempDoors.get(i).getDeviceUnique().substring(tempDoors.get(i).getDeviceUnique().length() - 4, tempDoors.get(i).getDeviceUnique().length())) < 0) {
                    if (StringUtils.isNotEmpty(tempDoors.get(i).getBatchNumber())) {
                        String endTime = iAppDeviceDao.getBatchNumberEndTime(tempDoors.get(i).getBatchNumber());
                        if (StringUtils.isNotEmpty(endTime)) {
                            Date endDate = DateUtil.fomatLongDate2(endTime);
                            Date nowDate = DateUtil.fomatLongDate2(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"));
                            Integer endDays = DateUtil.differentDays(nowDate, endDate);
                            if (endDays < -3) {
                                tempDoors.remove(i);
                                continue;
                            }
                        }else{
                            if(mark){
                                tempDoors.remove(i);
                                continue;
                            }
                        }
                    }else{
                        if(mark){
                            tempDoors.remove(i);
                            continue;
                        }
                    }
                    entrances.append(tempDoors.get(i).getDeviceUnique().substring(tempDoors.get(i).getDeviceUnique().length() - 4, tempDoors.get(i).getDeviceUnique().length()) + ",");
                }
            }
        }
        //开始拼接二维码
        StringBuilder heard=new StringBuilder("ITL:{L:");
        StringBuilder content = new StringBuilder();
        //协议版本 1Byte, Hex码
        content.append("V:"+AppQrcodeProtocolVersionEnum.NEW.getType()+",");
        //查询用户类型
        QrcodeUserInfoVO qrcodeUserInfo= iAppDeviceDao.getUserType(userId,projectId);
        //用户uid
        if(StringUtils.isNotBlank(qrcodeUserInfo.getUid())){
            content.append("U:"+qrcodeUserInfo.getUid()+",");
        }else{
            String uid;
            if(qrcodeUserInfo.getLastUid()!=null){
                uid = StringHandlerUtil.autlSupply(8,(qrcodeUserInfo.getLastUid()+1)+"","0");
                content.append("U:"+uid+",");
            }else{
                uid = StringHandlerUtil.autlSupply(8,"1","0");
                content.append("U:"+uid+",");
            }
            //保存uid
            iAppDeviceDao.updateUid(userId, projectId, uid);
        }
        //“M”表示用户类型标识符，用户类型固定1Byte，16进制表示。目前具体有以下类型：0x31授权二维码，0x32管理员用户，0x33表示业主或普通用户，0x34表示访客；0x35表示VIP用户、0x36表示残障用户；
        String[] types = StringHandlerUtil.splitString(qrcodeUserInfo.getUserLable());
        String type=new String();
        for(String t:types){
            if(StringUtils.isBlank(type)){
                type = t;
            }else if(t.equals("36")){
                type = t;
            }else if(t.equals("35") && type.equals(type)){
                type =t;
            }
        }
        if(StringUtils.isBlank(type)) {
            content.append("M:33,");
        }else if(type.equals("1")){
            //VIP
            content.append("M:35,");
        }else if(type.equals("2")){
            //障碍人士
            content.append("M:36,");
        }

        //房间编号
        Integer roomNo;
        if(StringUtils.isNotBlank(roomId)) {
            roomNo = iPropertyEquipDao.getRoomNoByRoomIdAndUserId(roomId,userId);
            if (roomNo == null) {
                Integer maxNo = iPropertyEquipDao.getMaxRoomNoByUserIdAndProjectId(userId, projectId);
                if (maxNo == null) {
                    roomNo = 1;
                } else {
                    roomNo = maxNo + 1;
                }
                iPropertyEquipDao.updateUserRoomNo(userId, roomId, roomNo);
            }
        }else{
            roomNo = 0;
        }
        content.append("H:"+Integer.toHexString(roomNo)+",");
        //批次号批次或流水号：“B:xxxx”其中“B”表示标识，批次值占用2个字节，用16进制表示0x0000—0xFFFF。
        content.append(valid == null || valid.getBatch() == null ? "I:0001," : "I:" + StringHandlerUtil.autlSupply(4, Integer.toHexString(valid.getBatch()), "0").toUpperCase() + ",");
        String startTime = DateUtil.fomatDate(DateUtil.reduceCurrentTime(new Date(),10*60*1000), DateUtil.YYMMDDHHMM);

        //启用时间
        content.append("T:" +startTime+ ",");
        //有效时间 hex 码
        content.append("P:0082,");
        String validCount;
        if(valid != null) {
            if (valid.getRoomChargeMode() == 1) {
                //有效次数 hex码
                content.append("S:" + (valid.getUsableCount() != null ? StringHandlerUtil.autlSupply(4,
                        Integer.toHexString(valid.getUsableCount()), "0").toUpperCase() : "01") + ",");
                validCount = StringHandlerUtil.autlSupply(4, valid.getUsableCount() != null ? Integer.toHexString(valid.getUsableCount()) : "01", "0").toUpperCase();
            } else {
                //有效次数 hex码
                content.append("S:0000,");
                validCount = "00";
            }
        }else{
            validCount = "00";
            //有效次数 hex码
            content.append("S:0000,");
        }
        if(validCount.length()>2){
            validCount=validCount.substring(2,4);
        }
        String value =startTime+"0082"+validCount;
        //用户拥有权限的电梯设备楼栋信息及房屋楼栋信息的交集 既最终用户所拥有的有权限的电梯设备楼栋信息
        Map<String, List<AppFloorDevicesVO>> userAuthFloorRoomsBuildAndUnit = new HashMap<>();
        //电梯楼层权限筛选
        Set<String> floorSet = new HashSet<>();
        if(StringUtils.isNotBlank(commonFloor)){
            Map<String,Object> commanFloors = JsonUtil.toObject(commonFloor,HashMap.class);
            for(String deviceUnique : commanFloors.keySet()){
                Optional<AppFloorDevicesVO> optional = floors.stream().filter(floor->floor.getDeviceUnique().equals(deviceUnique)
                        && StringHandlerUtil.splitStringToArray(floor.getLiveFloor()).stream().filter
                        (f->f.equals(commanFloors.get(deviceUnique).toString())).findFirst().isPresent()).findFirst();
                if(optional.isPresent()){
                    optional.get().setCommonChoiceFloor(commanFloors.get(deviceUnique).toString());
                }
            }
        }
        //组装用户电梯机号 按电梯楼层权限分组
        for(AppFloorDevicesVO floorVO : floors){
            List<AppFloorDevicesVO> list;
            //由于共享电梯项目 需求 上下都需收费，故将共同楼层权限加至二维码中，已和产品确认处理后只开放不点亮
            String commonFloorAuth = "";
            String[]  commonFloorStr = StringHandlerUtil.splitString(iAppDeviceDao.getCommonFloorByDeviceUnique(floorVO.getDeviceUnique()));
            if(commonFloorStr!=null && commonFloorStr.length>0 && valid !=null && valid.getProjectChargeMode() == 2){
                commonFloorAuth = iAppDeviceDao.getCommonFloorAuthByDeviceUnique(commonFloorStr,floorVO.getDeviceUnique());
            }
            if(StringUtils.isNotEmpty(floorVO.getLiveFloor()) && floorVO.getLiveFloor().startsWith(",")){
                floorVO.setLiveFloor(floorVO.getLiveFloor().substring(1,floorVO.getLiveFloor().length()));
            }
            if(StringUtils.isEmpty(commonFloorAuth) || valid == null || (valid != null && valid.getProjectChargeMode() == 1) ){
                if(floorSet.add(floorVO.getLiveFloor() +"c"+
                        (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""))){
                    list=new ArrayList<>();
                }else{
                    list=userAuthFloorRoomsBuildAndUnit.get(floorVO.getLiveFloor()+"c"+
                            (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""));
                }
                list.add(floorVO);
                userAuthFloorRoomsBuildAndUnit.put(floorVO.getLiveFloor() +"c"+
                        (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""),list);
            }else{
                if(floorSet.add(floorVO.getLiveFloor()+","+ commonFloorAuth +"c"+
                        (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""))){
                    list=new ArrayList<>();
                }else{
                    list=userAuthFloorRoomsBuildAndUnit.get(floorVO.getLiveFloor()+","+ commonFloorAuth+"c"+
                            (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""));
                }
                list.add(floorVO);
                userAuthFloorRoomsBuildAndUnit.put(floorVO.getLiveFloor()+","+ commonFloorAuth +"c"+
                        (StringUtils.isNotBlank(floorVO.getCommonChoiceFloor()) ? floorVO.getCommonChoiceFloor() : ""),list);
            }
        }
        //判断是否有电梯设备的权限
//        if(StringUtils.isNotBlank(floorUniques.toString())) {
//            //筛选出用户有权限的电梯设备楼栋信息
//            userAuthFloorRoomsBuildAndUnit = iAppDeviceDao.
//                    getUserAuthFloorRoomBuildAndUnit(StringHandlerUtil.splitString(floorUniques.toString()));
//        }

        String identifier;
        //电梯门禁标识 HEX码 如有电梯和门禁权限时为0x03；只有电梯而无门禁权限时为0x01；只有门禁权限时为0x02
        if(!userAuthFloorRoomsBuildAndUnit.isEmpty() && StringUtils.isNotBlank(entrances.toString())){
            identifier="03";
        }else if(!userAuthFloorRoomsBuildAndUnit.isEmpty()){
            identifier="01";
        }else if(StringUtils.isNotBlank(entrances.toString())){
            identifier="02";
        }else{
            identifier=("00");
        }
        if(!identifier.equals("00")) {
            //门禁
            if(!identifier.equals("01")) {
                //设置二维码的门禁数量
                String[] entranceDeviceUniques = StringHandlerUtil.splitString(entrances.toString());
                content.append("G:{");
                if (entranceDeviceUniques.length > 0 && entranceDeviceUniques.length < 255) {
                    //设置二维码的门禁权限 HEX码
                    String n1 = StringHandlerUtil.assembleQrcodeDeviceNum(entranceDeviceUniques);
                    String n2 = StringHandlerUtil.assembleNewDeviceNum(entranceDeviceUniques);
                    if(n1.length() > n2.length()) {
                        content.append("N2:" + n2);
                    }else{
                        content.append("N1:"+ n1);
                    }
                }else{
                    content.append("N3:0");
                }
                content.append("},");
            }
            //电梯
            if(!identifier.equals("02")) {
                int j = 1;
                //设置二维码的电梯权限
                for (Map.Entry<String, List<AppFloorDevicesVO>> floorMap : userAuthFloorRoomsBuildAndUnit.entrySet()) {
                    if (StringUtils.isNotBlank(floorMap.getKey()) && !floorMap.getKey().equals("c")) {
                        List<AppFloorDevicesVO> floorVos = floorMap.getValue();
                        //当前楼栋的电梯机号
                        StringBuilder currentFloorIds = new StringBuilder();
                        floorVos.forEach(cf -> {
                            currentFloorIds.append(cf.getDeviceUnique().substring(cf.getDeviceUnique().length() - 4, cf.getDeviceUnique().length()) + ",");
                        });
                        content.append("Q:{");
                        //设置机号权限N1：xxx
                        String n1 = StringHandlerUtil.assembleQrcodeDeviceNum(StringHandlerUtil.splitString(currentFloorIds.toString()));
                        String n2 = StringHandlerUtil.assembleNewDeviceNum(StringHandlerUtil.splitString(currentFloorIds.toString()));
                        if(n1.length() > n2.length()){
                            content.append("N2:" + n2 + ",");
                        }else{
                            content.append("N1:" + n1 + ",");
                        }
                        //设置有权限的楼层数量 HEX码
                        String fl = floorMap.getKey();
                        String[] floorNo = StringHandlerUtil.splitString(fl.substring(0,fl.indexOf("c")));
                        String chCommonFloor = fl.substring(fl.indexOf("c") + 1, fl.length());
                        if (floorNo.length == 112) {
                            content.append("X3:0,");
                        } else {
                            n1 = StringHandlerUtil.assembleQrcodeDeviceNum(floorNo);
                            n2 = StringHandlerUtil.assembleNewDeviceNum(floorNo);
                            if(n1.length() > n2.length()) {
                                content.append("X2:" + n2 + ",");
                            }else{
                                content.append("X1:" + n1 + ",");
                            }
                        }
                        //设置直达楼层
                        if((StringUtils.isNotBlank(chCommonFloor) && !chCommonFloor.equals("c") &&
                                chCommonFloor.length() > chCommonFloor.indexOf("c")&&!chCommonFloor.equals("null")) || (valid!=null && valid.getProjectChargeMode()==2)){
                            if(valid!=null && valid.getProjectChargeMode()==2){
                                String naturalFloor = iAppDeviceDao.getNaturalFloorByRoomNum(valid.getRoomNum().substring(0, 2), floorVos.get(0).getDeviceUnique());
                                if(StringUtils.isNotBlank(naturalFloor)){
                                    content.append("Y:" +StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(naturalFloor)).toUpperCase(), "0"));
                                }
                            }else{
                                content.append("Y:" +StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(chCommonFloor)).toUpperCase(), "0"));
                            }
                        }else{
                            for(int i=0; i < floorVos.size() ; i++ ){
                                if(StringUtils.isNotBlank(floorVos.get(i).getCommonChoiceFloor())){
                                    content.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floorVos.get(i).getCommonChoiceFloor())).toUpperCase(), "0"));
                                    break;
                                }
                                if(i == floorVos.size()-1){
                                    //没有直达楼层设置00
                                    if(projectId.equals("88888888")&&qrcodeRunEnvironment.equals("test")) {
                                        //201环境下项目88888888设置默认楼层为7
                                        content.append("Y:07");
                                    }else{
                                        //产品定义如若项目开启共享电梯收费模式，则直达楼层为生成二维码所选房间对应的楼层
                                        if(valid!=null && valid.getProjectChargeMode()==2){
                                            String naturalFloor = iAppDeviceDao.getNaturalFloorByRoomNum(valid.getRoomNum().substring(0, 2), floorVos.get(i).getDeviceUnique());
                                            content.append("Y:" +StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(naturalFloor)).toUpperCase(), "0"));
                                        }else{
                                            content.append("Y:00");
                                        }
                                    }
                                }
                            }
                        }
                        content.append("},");
                        j++;
                    }
                }
            }
        }
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(projectId);
        String mac="K:"+DesEncryptUtil.newOwnerAndVisitorMacEncrypt(value, projectKey, content.toString());
        String qrcode = heard.toString()+ StringHandlerUtil.autlSupply(4,Integer.toHexString((content + mac).length()).toUpperCase(),"0") +","+content+mac+"}";
        //保存用户二维码
        iAppDeviceDao.updateUserQrCode(userId,projectId,qrcode.toString(),DateUtil.fomatDate1(DateUtil.addCurrentTime(7)),roomId, System.currentTimeMillis() + 120 * 60 * 1000);
        return qrcode;
    }





    /**
     * <desc>
     *      推送云对讲设备端拉取业主认证增量信息
     * </desc>
     *
     * @param projectId 项目id
     * @param userId    用户id
     * @param commandType 业务指令
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/23
     */
    @Override
    public Integer pushCloudDeviceAuth(String projectId, String userId,Integer commandType) throws Exception {
        //推送设备更新信息
        if(projectId==null){
            //如果项目id为null 查询该用户所有项目id
            projectId=iAppDeviceDao.getUserAllProjectId(userId);
        }
        List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
        if(StringUtils.isNotBlank(projectId)) {
            String[] projectIds=StringHandlerUtil.splitString(projectId);
            for(String project:projectIds) {
                Map<String,Object> projectMap=new HashMap<>();
                projectMap.put("userId",userId);
                projectMap.put("projectId",project);
                if(commandType == SmartCommunityEnum.PUSH_USER_PROJECT.getCommandType()){
                    DeviceBusinessChangeLogPO po=new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT, JsonUtil.toJSON(projectMap),project);
                    changes.add(po);
                }else if(commandType == SmartCommunityEnum.PUSH_ROOM.getCommandType()){
                    //获取用户已认证不同楼栋的房屋信息
                    List<Map<String, Object>> rooms = iAppDeviceDao.getUserRoomsInfos(userId, project);
                    List<Map<String,Object>> roomList=new ArrayList<>();
                    //获取用户所属房间楼栋的云对讲设备及所有的围墙机
                    if (!rooms.isEmpty()) {
                        rooms.forEach(room -> {
                            String roomId=StringHandlerUtil.getNullOrStringForObject(room.get("roomId"));
                            if(StringUtils.isNotBlank(roomId)) {
                                String[] rd=StringHandlerUtil.splitString(roomId);
                                for(String r : rd){
                                    Map<String,Object> roomMap=new HashMap<>();
                                    roomMap.put("roomId", r);
                                    roomList.add(roomMap);
                                }
                            }
                        });
                        //推送房间更新消息
                        DeviceBusinessChangeLogPO po=new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM,JsonUtil.toJSON(roomList),project);
                        changes.add(po);
                        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(projectId,CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD,JsonUtil.toJSON(roomList));
                        elevatorChanges.add(elevatorPo);
                        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(projectId,CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                        entranceChanges.add(entrancePO);
                    }
                }
            }
            JSONObject dataJs = new JSONObject();
            dataJs.put("data",changes);
            //发送云对讲业务指令
            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE, RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
            if(commandType == SmartCommunityEnum.PUSH_ROOM.getCommandType()){
                dataJs.put("data",elevatorChanges);
                //推送云电梯房间信息
                messageSender.send(
                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                        JsonUtil.toJSON(dataJs),
                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                //发送云门禁指令
                dataJs.put("data",entranceChanges);
                messageSender.send(
                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                        JSON.toJSONString(dataJs),
                        RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
                );
            }
        }
        return 1;
    }


    /**
     * <desc>
     *      获取授权二维码
     * </desc>
     *
     * @param projectId 项目id
     * @param tlv 仅二维码SDK调用时传
     * @return
     * @author Jiaqi.X
     * @createDate 2017/12/13
     */
    public String getAuthQrcode(String projectId,String tlv) throws Exception {
        StringBuilder validTime=new StringBuilder(DateUtil.fomatDate(DateUtil.reduceCurrentTime(new Date(),10*60*1000), DateUtil.YYMMDDHHMM));
        //流水号：1Byte，Hex码
        try{
            writeLock.lock();
            String cacheKey=RedisConstant.REDIS_APP_AUTHORIZE_QRCODE_SERIAL_NUMBER_CACHE+projectId+ DateUtil.fomatDate(new Date(), DateUtil.YYYYMMDDHHMM);
            Integer serialNumber=(Integer)redisService.getObject(cacheKey, Integer.class);
            if(serialNumber!=null){
                validTime.append(StringHandlerUtil.autlSupplyLast(2,serialNumber.toString(),"0"));
            }else{
                serialNumber=1;
                validTime.append(StringHandlerUtil.autlSupplyLast(2,serialNumber.toString(),"0"));
            }
            redisService.set(cacheKey,RedisConstant.REDIS_APP_AUTHORIZE_QRCODE_SERIAL_NUMBER_CACHE_TIME,Integer.valueOf(serialNumber)+1);
        }catch (Exception e){
            throw e;
        }finally{
            writeLock.unlock();
        }
        //有效时间 0C 十六进制*10分钟
        validTime.append("10");
        //有效次数
        validTime.append("01");
        //获取项目秘钥
        String projectKey=iAppDeviceDao.getQrcodeProjectKey(projectId).toUpperCase();
        //获取加密后的项目秘钥
        String encriptProjKey=DesEncryptUtil.ProjKeyEncrypt(DesEncryptUtil.QRCODE_INIT_KEY, projectId, projectKey);
        //拼接二维码
        String qrCode=AppQrcodeProtocolVersionEnum.INITIAL.getType()+AppQrcodeUserTypeEnum.AUTHORIZE.getType()+projectId+encriptProjKey+validTime.toString();
        qrCode+="80";
        String[] tlvs = StringHandlerUtil.splitString(tlv);
        String qrtlvs = new String();
        for(String v : tlvs){
            if(StringUtils.isBlank(qrtlvs)){
                qrtlvs+="A001"+v;
            }else{
                qrtlvs+="A101"+v;
            }
        }
//        if(tlvs.length ==1 ){
//            qrtlvs+="A100";
//        }
        qrCode+=qrtlvs;
        //获取二维码mac值
        qrCode=qrCode+DesEncryptUtil.qrcodeAuthMacEncrypt(validTime.toString(), DesEncryptUtil.QRCODE_INIT_KEY, projectId, qrCode);
//        LOG.info("工程app获取二维码读头，二维码内容：" + qrCode + "，项目id：" + projectId + "，项目秘钥：" + projectKey);
        return qrCode;
    }

    /**
     * <desc>
     *      根据设备唯一码获取门禁类型
     * </desc>
     *
     * @param deviceUnique
     * @return
     * @author Jugaung.S
     * @createDate 2019/05/26
     */
    @Override
    public Integer getEntranceTypeInfo(String deviceUnique) {
        return iAppDeviceDao.getEntranceTypeInfo(deviceUnique);
    }

    /**
     * <desc>
     *      用户读取欠费消息
     * </desc>
     *
     * @return 欠费消息
     * @author wangzhi
     * @createDate 2019/05/28
     */
    @Override
    public Map<String, String> getArrearageInfo(String projectId, String roomId, String deviceUnique, String userId, String type, String deviceType) throws Exception {
        Map<String, String> data = new HashMap<>();
        // 查询最大欠费天数
        Integer maxDays;
        // 不欠费房间数量
        Integer notArrRoomCount;
        if (StringUtils.isBlank(roomId) && StringUtils.isNotBlank(deviceUnique) && StringUtils.isNotBlank(userId)) {
            // 人脸识别时房间id为空，使用设备序列号和用户id查询房间id
            roomId = iAppDeviceDao.getRoomIdByDeviceUniqueAndUserId(deviceUnique, userId, projectId, Integer.parseInt(deviceType));
        }
        if (StringUtils.isNotBlank(roomId)) {
            maxDays = iAppDeviceDao.getMaxArrearDaysByRoomId(StringHandlerUtil.splitStringList(roomId), projectId);
            // 判断是否有房间不欠费，如果有，则不限制权限
            notArrRoomCount = iAppDeviceDao.getNotArrRoomCountByRoomId(StringHandlerUtil.splitStringList(roomId), projectId);
        } else {
            maxDays = iAppDeviceDao.getMaxArrearDaysByUserId(userId, projectId);
            // 判断是否有房间不欠费，如果有，则不限制权限
            notArrRoomCount = iAppDeviceDao.getNotArrRoomCountByUserId(userId, projectId);
        }
        String pointOut = iAppDeviceDao.getPropertyValueDeploy(projectId, 4, maxDays);
        if (pointOut == null) {
            pointOut = "";
        }
        String propertyValueDeploy = iAppDeviceDao.getPropertyValueDeploy(projectId, Integer.parseInt(deviceType), maxDays);
        if (propertyValueDeploy == null) {
            propertyValueDeploy = "";
        }
        List<String> propertyValueDeployList = StringHandlerUtil.splitStringList(propertyValueDeploy);
        if (propertyValueDeployList.contains(type) && notArrRoomCount == 0) {
            data.put("type","2");
            String typeName = "";
            switch (type) {
                case "1":
                    typeName = "刷脸";
                    break;
                case "2":
                    typeName = "读卡";
                    break;
                case "3":
                    typeName = "密码";
                    break;
                case "4":
                    typeName = "蓝牙";
                    break;
                case "5":
                    typeName = "二维码";
                    break;
                case "6":
                    typeName = "指纹";
                    break;
                default:
                    break;
            }
            if(deviceType.equals("3") && type.equals("4")){
                typeName = "呼叫";
            }
            data.put("hint","您有费用未缴，" + typeName + "功能已被禁用");
        } else if ("1".equals(pointOut) || (propertyValueDeployList.contains(type) && notArrRoomCount != 0)){
            data.put("type","1");
            // 查询未缴账单数
//            Integer feeCount;
//            if (StringUtils.isNotBlank(roomId)) {
//                feeCount = iAppDeviceDao.getUnpaidFeeCountByRoomId(StringHandlerUtil.splitStringList(roomId));
//            } else {
//                feeCount = iAppDeviceDao.getUnpaidFeeCountByUserId(userId, projectId);
//            }
            data.put("hint","您有未缴物业账单，请及时处理");
        } else {
            data.put("type","3");
            data.put("hint","");
        }
        return data;
    }

    /**
     * <desc>
     *      根据楼层名称获取实际楼层和权限标识
     * </desc>
     *
     * @param floors
     * @param deviceUnique
     * @return
     * @author Jiaqi.X
     * @createDate 2019/08/15
     */
    public Map<String, Object> getFloorNumAndNaturalFloorByLogicFloor(String floors, String deviceUnique) {
        return iAppDeviceDao.getFloorNumAndNaturalFloorByLogicFloor(StringHandlerUtil.splitString(floors), deviceUnique);
    }

    /**
     * <desc>
     *      获取当前用户的临时权限
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @return
     * @author Juguang.S
     * @createDate 2019/09/02
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppUserDevicesVO> getUserDevicesInfo(String userId,String projectId) throws Exception {
        List<AppUserDevicesVO> deviceList = new ArrayList<>();
        //获取用户的临时权限的门禁设备机号
        List<Map<String, Object>> doorAuth = iAppDeviceDao.getDoorAuthByVisitor(userId, projectId);
        AppEntranceOrCloudIntercomAuthVO doorVO = StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(), doorAuth);
        if (doorAuth != null && !doorAuth.isEmpty()) {
            String[] doors = doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]);
            if (doors != null && doors.length > 0) {
                List<AppUserDevicesVO> list = iAppDeviceDao.getDoorDevicesByVisitor(userId, projectId, doors);
                deviceList.addAll(list);
            }
        }
        //获取用户的临时权限的云对讲设备机号
        List<Map<String, Object>> cloudAuth = iAppDeviceDao.getCloudIntercomsAuthByVisitor(userId, projectId);
        AppEntranceOrCloudIntercomAuthVO cloudVO = StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType(), cloudAuth);
        if (cloudVO != null) {
            String[] cloudIntercoms = cloudVO.getDeviceIds().toArray(new String[cloudVO.getDeviceIds().size()]);
            if (cloudIntercoms != null && cloudIntercoms.length > 0) {
                List<AppUserDevicesVO> cloudTalkList = iAppDeviceDao.getCloudIntercomsByVisitor(userId, projectId, cloudIntercoms);
                deviceList.addAll(cloudTalkList);
            }
        }
        //获取用户的临时权限的电梯设备机号
        List<AppElevatorAuthDTO> auth = iAppDeviceDao.getFloorAuthByVisitor(userId, projectId);
        if (!auth.isEmpty()) {
            AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
            String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
            if (devices.length > 0) {
                List<AppUserDevicesVO> elevatorList = iAppDeviceDao.getFloorDevicesByVisitor(userId, projectId, devices);
                deviceList.addAll(elevatorList);
            }
        }
        return deviceList;
    }

    /**
     * <desc>
     *      保存或修改访客的设备标签
     * </desc>
     *
     * @param deviceMarkDTO 创建或修改标签的信息
     * @return
     * @author Juguang.S
     * @createDate 2019/09/02
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String saveOrUpdateDeviceMark(CreateDeviceMarkDTO deviceMarkDTO) throws Exception{
        VisitorDeviceMarkInfoPO markInfoPO = new VisitorDeviceMarkInfoPO();
        BeanUtils.copyProperties(deviceMarkDTO,markInfoPO);
        //标签ID为空则为新增 否则为修改
        if(StringUtils.isEmpty(deviceMarkDTO.getMarkId())){
            String markId = LogicIdUtil.bussinessId();
            markInfoPO.setMarkId(markId);
            markInfoPO.setUserId(deviceMarkDTO.getLoginUserId());
            markInfoPO.setCreateTime(new Date());
            iAppDeviceDao.save(SqlUtil.durableData(markInfoPO,PlatformConstants.TABLE_SAVE));
            return markId;
        }else{
            //VisitorDeviceMarkInfoPO oldmMarkInfoPO = iAppDeviceDao.getDeviceMarkInfo(deviceMarkDTO.getMarkId());
            markInfoPO.setUpdateTime(new Date());
            iAppDeviceDao.update(SqlUtil.durableData(markInfoPO, PlatformConstants.TABLE_UPDATE));
            return deviceMarkDTO.getMarkId();
        }
    }

    /**
     * <desc>
     *      获取当前用户的临时设备标签
     * </desc>
     *
     * @param userId 用户编号
     * @param projectId 项目编号
     * @return
     * @author Juguang.S
     * @createDate 2019/09/02
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<VisitorDeviceMarkInfoVO> getDeviceMark(String userId, String projectId) throws Exception{
        List<VisitorDeviceMarkInfoVO> markList= iAppDeviceDao.getDeviceMarkInfoByUserId(userId,projectId);
        if(markList!=null && !markList.isEmpty()){
            for(VisitorDeviceMarkInfoVO markInfoVO : markList){
                if(StringUtils.isEmpty(markInfoVO.getDeviceUniques())){
                    continue;
                }
                String[] deviceUnqiueArr = markInfoVO.getDeviceUniques().split(",");
                StringBuffer stringBuffer = new StringBuffer();
                for(String deviceUnique : deviceUnqiueArr){
                    Integer deviceType = Integer.parseInt(StringHandlerUtil.copySubStr(deviceUnique, 8, 1));
                    switch (PropertyEquipTypeEnum.getByEquipType(deviceType)) {
                        case ELEVATOR:
                            DeviceElevatorInfoPO elevator = iPropertyElevatorDao.getByDeviceUnique(deviceUnique);
                            if (elevator != null) {
                                stringBuffer.append(elevator.getDeviceName()).append(",");
                            }
                            break;
                        case ENTRANCE:
                            //查询门禁信息
                            DeviceEntranceInfoPO entrance = iDeviceEntranceInfoDao.getByDeviceUnique(deviceUnique);
                            if (entrance != null) {
                                stringBuffer.append(entrance.getDeviceName()).append(",");
                            }
                            break;
                        case CLOUD_INTERCOM:
                            //查询云对讲信息
                            DeviceCloudIntercomInfoProductTypeVO cloudIntercom = iDeviceCloudIntercomInfoDao.getProductTypeByDeviceUnique(deviceUnique, null);
                            if (cloudIntercom != null) {
                                stringBuffer.append(cloudIntercom.getDeviceName()).append(",");
                            }
                            break;
                        default:
                            return null;
                    }

                }
                stringBuffer.deleteCharAt(stringBuffer.lastIndexOf(","));
                markInfoVO.setDeviceNames(stringBuffer.toString());
            }
        }
        return markList;
    }

    /**
     * <desc>
     *      删除设备标签
     * </desc>
     *
     * @param markId 标签ID
     * @return
     * @author Juguang.S
     * @createDate 2019/09/03
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer deleteDeviceMark(String markId) throws Exception{
        return iAppDeviceDao.deleteDeviceMark(markId);
    }

    /**
     * <desc>
     *      根据房间编号和项目编号获取房间下的业主编号
     * </desc>
     *
     * @param roomId 房间ID
     * @param projectId 项目ID
     * @return
     * @author Juguang.S
     * @createDate 2019/09/03
     */
    @Override
    public String getOwnerUserIdByroomId(String roomId,String projectId) throws Exception{
        return iAppDeviceDao.getOwnerUserIdByroomId(roomId,projectId);
    }

    /**
     * <desc>
     *      获取当前用户的临时电梯设备列表
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @return
     * @author Juguang.S
     * @createDate 2019/09/04
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppFloorDevicesVO> getUserTemporaryAuthFloorDevices(String userId, String projectId) {
            //获取电梯的授权设备信息，居住楼层权限，常用居住楼层，常用公共楼层，有效时间
        List<AppFloorDevicesVO> list = null;
            List<AppElevatorAuthDTO> auth = iAppDeviceDao.getFloorAuthByVisitor(userId, projectId);
            if (auth.isEmpty()) {
                return new ArrayList<>();
            }
            AppElevatorAuthVO elevator = StringHandlerUtil.convertElevatorAuth(auth);
            String[] devices = StringHandlerUtil.splitString(elevator.getDeviceId());
            List<String> controllerDevices = new ArrayList<>();
            for(String device : devices){
                controllerDevices.add(projectId+"1"+device);
            }
            if (devices.length > 0) {
                list = iAppDeviceDao.getFloorDevices(userId, projectId, devices);
                //将筛选的用户电梯权限详情放入用户权限信息
                if (null != list && !list.isEmpty()) {
                    floor:for(int j = list.size() - 1 ; j >= 0 ;j--) {
                        AppFloorDevicesVO floorDevice = list.get(j);
                        //设置楼层权限
                        elevator.getElevatorAuth().forEach(authInfo -> {
                            if (floorDevice.getDeviceId().equals(authInfo.getDeviceId())) {
                                List<String> lifeFloors = new ArrayList<>();
                                //获取电梯起始楼层及结束楼层
                                Map<String, Object> minAndMaxFloor = iAppDeviceDao.getMinAndMaxFloor(floorDevice.getDeviceUnique());
                                if (minAndMaxFloor != null) {
                                    Integer startFloor = minAndMaxFloor.get("minFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("minFloor").toString()).intValue();
                                    Integer endFloor = minAndMaxFloor.get("maxFloor") == null ? null : Double.valueOf(minAndMaxFloor.get("maxFloor").toString()).intValue();
                                    if (startFloor != null) {
                                        String[] tempLifeFloor = StringHandlerUtil.splitString(authInfo.getLiveFloor());
                                        for (String f : tempLifeFloor) {
                                            if (Integer.valueOf(f) <= endFloor && Integer.valueOf(f) >= startFloor) {
                                                lifeFloors.add(f);
                                            }
                                        }
                                        authInfo.setLiveFloor(StringUtils.join(lifeFloors.toArray(new String[lifeFloors.size()]), ","));
                                    }
                                }
                                //设置常用居住楼层
                                floorDevice.setLiveFloor(StringHandlerUtil.filterLastComma(authInfo.getLiveFloor()));
                            }
                        });
                    }
                }
            }

        return list == null ? new ArrayList<>() : list;
    }

    /**
     * <desc>
     *      获取项目的云服务费最小过期时间
     * </desc>
     *
     * @param projectId 项目Id
     * @return 项目的云服务费最小过期时间
     * @author wangzhi
     * @createDate 2020/02/26
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getProjectCloudServiceCostMinEndTime(String projectId) throws Exception {
        List<String> oldBatchNumberArr = new ArrayList<>();
        //查询出需排除的旧批次集合
        List<String> oldBatchNumberList = iAppDeviceDao.getOldBatchNumberByProjectId(projectId);
        for (String oldBatchNumbers : oldBatchNumberList) {
            String[] oldBatchNumberOneArr = oldBatchNumbers.split(",");
            oldBatchNumberArr.addAll(Arrays.asList(oldBatchNumberOneArr));
        }
        //获取项目下最近批次号过期时间
        return iAppDeviceDao.getBatchNumberEndTimeByProjectId(projectId, oldBatchNumberArr.isEmpty() ? null : oldBatchNumberArr);
    }

    /**
     * <desc>
     *      获取游客模式下有公共楼层的电梯设备
     * </desc>
     *
     * @param projectId 项目Id
     * @return 游客模式下有公共楼层的电梯设备
     * @author wangzhi
     * @createDate 2020/05/06
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppFloorDevicesVO> getGuestFloorList(String projectId) throws Exception {
        List<AppFloorDevicesVO> floorGuestList = iAppDeviceDao.getGuestFloorList(projectId);
        List<AppFloorDevicesVO> floorList = new ArrayList<>();
        if (floorGuestList != null && !floorGuestList.isEmpty()) {
            List<String> controllerDevices = new ArrayList<>();
            floorGuestList.forEach(floor -> controllerDevices.add(floor.getDeviceUnique()));
            for (AppFloorDevicesVO appFloorDevicesVO : floorGuestList) {
                // 检索电梯是否是云电梯，如果是则查询是否绑定控制器
                if (StringUtils.isNotBlank(appFloorDevicesVO.getLiftType()) && !appFloorDevicesVO.getLiftType().equals("1")) {
                    Map<String, Object> controllers = iAppDeviceDao.getControllerDeviceUniqueByElevatorDeviceUniques(appFloorDevicesVO.getDeviceUnique(), controllerDevices.toArray(new String[controllerDevices.size()]));
                    if (controllers != null && controllers.get("groupConId") != null) {
                        if (!controllers.get("status").toString().equals("1")) {
                            continue;
                        }
                        appFloorDevicesVO.setGroupConId(controllers.get("groupConId").toString());
                        appFloorDevicesVO.setRelatedDeviceId(controllers.get("deviceUnique").toString());
                    }
                }
                appFloorDevicesVO.setFloorAuth(StringHandlerUtil.filterLastComma(StringHandlerUtil.getAuthCodeBynNturalFloors("")).toUpperCase());
                appFloorDevicesVO.setValiTime(DateUtil.formatStringToDate(StringHandlerUtil.filterLastComma("2099-12-31 23:59:59"), DateUtil.DATE_FORMAT_TYPE1).getTime() + "");
                floorList.add(appFloorDevicesVO);
            }
        }
        return floorList;
    }

    /**
     * <desc>
     *      获取个人电梯、群控器设备排序信息
     * </desc>
     *
     * @param userId    用户编号
     * @param projectId 项目编号
     * @return 个人电梯、群控器设备排序信息
     * @author wangzhi
     * @createDate 2020/05/07
     */
    @Override
    public String getUserElevatorControllerOrder(String userId, String projectId) throws Exception {
        return iAppDeviceDao.getUserElevatorControllerOrder(userId, projectId);
    }

    /**
     * <desc>
     *      用户是否是vip
     * <desc/>
     *
     * @param userId 用户编号
     * @param projectId 项目编号
     * @return
     * @author pengwei
     * @createDate 2020-11-13
     */
    @Override
    public boolean appUserIsVip(String userId, String projectId) throws Exception {
        //用户标签，1-VIP，2-障碍人士，多个英文逗号连接
        String  userLabel  = iAppDeviceDao.getAppUserLabel(userId,projectId);
        if(StringUtils.isNotEmpty(userLabel)){
            String[]  labelList =  userLabel.split(",");
            for(String  label:labelList){
                //1是vip
                if("1".equals(label)){
                    return  true;
                }
            }
        }
        return false;
    }


    /**
     *<desc>
     * 获取公共楼层和常用楼层
     *</desc>
     *
     * @Author  chengshican
     * @Date   2020-11-19 16:32
     * @Param  userId 用户编号
     * @param  projectId 项目编号
     * @Return
     * @Exception
     *
     */
    @Override
    public Map<String, Object>  getAppCommonAndPublicByUserId(String userId, String projectId)throws Exception{
       return iAppDeviceDao.getAppCommonAndPublicByUserId(userId,projectId);
    }

    /**
     * <desc>
     * 是否vip预约呼梯中
     * </desc>
     *
     * @param deviceUnique
     * @return
     * @author caoshuai
     * @createDate 2020/12/27 14:43
     */
    @Override
    public Boolean getIsVipCall(String deviceUnique) {
        String projectId = StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique);
        String iotFlag = iAppDeviceDao.iotByProjectId(projectId);
        if("1".equals(iotFlag)) {
            return false;
        }
        Map<String, Object> cloudElevatorCallStatusInfo = iAppDeviceDao.getCloudElevatorCallStatusInfo(deviceUnique);

        if(null == cloudElevatorCallStatusInfo || null == cloudElevatorCallStatusInfo.get("recordIds")) {
            return false;
        }
        String controllerCmd = iAppDeviceDao.getCloudControllerInfo(cloudElevatorCallStatusInfo.get("groupConId") + "");
        if(StringUtils.isBlank(controllerCmd)) {
            return false;
        }
        String elevatorCmd = iAppDeviceDao.getCloudElevatorInfo(deviceUnique);
        if(StringUtils.isBlank(elevatorCmd)) {
            return false;
        }

        List cloudControllerElevatorInfo = iAppDeviceDao.getCloudControllerElevatorInfo(cloudElevatorCallStatusInfo.get("groupConId") + "");
        if(null == cloudControllerElevatorInfo || cloudControllerElevatorInfo.size() != 1) {
            return false;
        }

        String userLabel = iAppDeviceDao.getCloudElevatorOperateRecordInfo(cloudElevatorCallStatusInfo.get("recordIds") + "");
        if(null == userLabel || !userLabel.contains("1")) {
            return false;
        }

        return true;
    }

    /**
     *      获取用户门禁设备列表 暂于人脸一体式门禁权限机号只处理在二维码中 设备列表暂且隐藏 待设备列表放开时再将此方法删除
     * </desc>
     *
     * @param userId 用户Id
     * @param projectId 项目Id
     * @param updateCache 是否更新缓存 1是 0否
     * @return
     * @author Juguang.S
     * @createDate 2020/10/21
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppDoorDevicesVO> getDoorDevicesByTemp(String userId,String projectId,Integer updateCache) throws Exception {
        //读取缓存信息
//        List<AppDoorDevicesVO> list= (List<AppDoorDevicesVO>) redisService.decodeObject(
//                RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId, new TypeReference<List<AppDoorDevicesVO>>() {});
        //由于和权限相关已变更，就会把不查询一体式门禁的权限更新至缓存，故此处暂先不读缓存
        List<AppDoorDevicesVO> list= null;
        //如果list为null或者需要更新缓存并且list不为null的情况下，重新从数据库读取信息并设置缓存
        if((updateCache == 0 && list == null) || (updateCache == 1)) {
            //获取用户有权限的门禁设备机号
            List<Map<String,Object>> doorAuth = iAppDeviceDao.getDoorAuth(userId, projectId);
            AppEntranceOrCloudIntercomAuthVO doorVO=StringHandlerUtil.converEntranceOrCloudIntercomAuth(PropertyEquipTypeEnum.ENTRANCE.getType(),doorAuth);
            if (doorAuth!=null&&!doorAuth.isEmpty()) {
                String[] doors = doorVO.getDeviceIds().toArray(new String[doorVO.getDeviceIds().size()]);
                if(doors !=null && doors.length > 0) {
                    list = iAppDeviceDao.getDoorDevicesByTemp(userId, projectId, doors);
                    if (null != list && !list.isEmpty()) {
                        //解析排序值
                        String[] orders = StringHandlerUtil.splitString(list.get(0).getPosition());
                        for (AppDoorDevicesVO door : list) {
                            door.setDoorAuth("8");
                            door.setPosition(parseDeviceOrder(orders, door.getDeviceUnique()));
                            door.setValiTime(DateUtil.formatStringToDate(doorVO.getValiTime(), DateUtil.YYMMDDHHMMSS).getTime() + "");
                        }
//                        redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
//                                RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, list);
                    }else{
                        redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                                RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                    }
                }else{
                    redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                            RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
                }
            } else {
                redisService.set(RedisConstant.REDIS_APP_USER_DEVICE_DOOR_CACHE + userId + projectId,
                        RedisConstant.REDIS_APP_USER_DEVICE_CACHE_TIME, new ArrayList<>());
            }
        }
        return list == null ? new ArrayList<>() : list;
    }


    /**
     * <desc>
     * 通过门禁设备机号查询门禁所在地址
     * </desc>
     *
     * @param deviceUnique
     * @author: chengshican
     * @Date: 2021-01-04 12:11
     */
    @Override
    public  List<Map> getDeviceEntranceBridgeInfoByDeviceUnique(String deviceUnique) {
        return iAppDeviceDao.getDeviceEntranceBridgeInfoByDeviceUnique(deviceUnique);
    }


    /**
     *<desc>
     * 通过平板设备机号查询所在地址
     *</desc>
     *
     * @Author  chengshican
     * @Date   2021-01-28 10:33
     * @Param
     * @Return
     * @Exception
     *
     */
    @Override
    public  List<Map> getPadBridgeInfoByDeviceUnique(String deviceUnique) {
        return iAppDeviceDao.getPadBridgeInfoByDeviceUnique(deviceUnique);
    }


    /**
     * <desc>
     * 获取用户标签
     * </desc>
     *
     * @param userId
     * @return
     * @author caoshuai
     * @createDate 2021/1/4 17:18
     */
    @Override
    public String getUserLabel(String userId, String projectId) {

        return iAppDeviceDao.getUserLabel(userId, projectId);
    }

    /**
     * <desc>
     * 预约呼梯仅供于前海嘉里非标项目调用
     * </desc>
     *
     * @param deviceUnique  设备序列号
     * @param startingFloor 起始楼层（真实楼层）
     * @param gotoFloor     目的楼层（真实楼层）
     * @return
     * @author Juguang.S
     * @createDate 2020-03-11
     */
    @Override
    public Map<String,String> cloudElevatorCallByNonStandard(String deviceUnique,String startingFloor, String gotoFloor,String userId) throws Exception{

        Map<String, String> returnMap = new HashMap();
        //组装向线下平台发送呼梯请求的参数
        Map<String, Object> params = new HashMap();
        params.put("ctrlNo",deviceUnique);
        params.put("startFloor",startingFloor);
        params.put("targetFloor",gotoFloor);
        Map<String, Object> paramsData = new HashMap();
        paramsData.put("dataJson",JSON.toJSONString(params));

        String result = HttpsPost.doPost(offlinePLatformDomainByCallElevatorUrl, paramsData, 20000, 20000);

        if (StringUtils.isBlank(result)) {
            LOG.info("【线下平台返回结果为空】");
            returnMap.put("errorMsg","1");
        }
        Map<String, Object> resultMap = JSONObject.parseObject(result, HashMap.class);
        if ("0".equals(resultMap.get("code") + "") && resultMap.get("data") != null) {
            LOG.info("【线下平台返回成功结果】"+JSON.toJSONString(resultMap));
            returnMap.put("deviceName",JSONObject.parseObject(resultMap.get("data") + "", HashMap.class).get("devName") + "");
            returnMap.put("deviceUnique",JSONObject.parseObject(resultMap.get("data") + "", HashMap.class).get("ctrlNo") + "");

            //保存通行记录
            //验证是否是完整信息
            TimeTaskDevicePassRecordPO po = new TimeTaskDevicePassRecordPO();
            po.setPdId(LogicIdUtil.bussinessId());
            po.setUserId(userId);
            po.setProjectId(StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique));
            po.setDeviceUnique(returnMap.get("deviceUnique")+"");
            po.setPassTime(new Date());
            po.setDeviceType(PropertyEquipTypeEnum.ELEVATOR.getType());
            //查询设备名称
            //if(StringUtils.isBlank(po.getDeviceName()) && StringUtils.isNotBlank(po.getDeviceUnique()) && po.getDeviceType()!=null){
            //    po.setDeviceName(iAppHomeDao.getDeviceNameByDeviceUnique(po.getDeviceUnique(),po.getDeviceType()));
            //}
            po.setDeviceName(returnMap.get("deviceName")+"");
            po.setOpenType(19);
            po.setOpenCount(1);
            po.setStatus(DataStatusEnum.NORMAL.getType());
            po.setUploadTime(new Date());
            po.setCreateTime(po.getUploadTime());
            po.setSynchro(0);
            po.setIsOpen(0);
            iAppDeviceDao.save(SqlUtil.durableData(po,PlatformConstants.TABLE_SAVE));
        } else{
            LOG.info("【线下平台返回失败结果】"+JSON.toJSONString(resultMap));
            returnMap.put("errorMsg","2");
            returnMap.put("message",resultMap.get("msg") + "");
        }

        return returnMap;
    }

}
